// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {isString} from '../base/object_utils';
import {RecordConfig} from '../controller/record_config_types';

export const BUCKET_NAME = 'perfetto-ui-data';
import {v4 as uuidv4} from 'uuid';
import {State} from './state';
import {defer} from '../base/deferred';
import {Time} from '../base/time';

export class TraceGcsUploader {
  state: 'UPLOADING' | 'UPLOADED' | 'ERROR' = 'UPLOADING';
  error = '';
  totalSize = 0;
  uploadedSize = 0;
  uploadedUrl = '';
  onProgress: () => void;
  private req: XMLHttpRequest;
  private reqUrl: string;
  private donePromise = defer<void>();
  private startTime = performance.now();

  constructor(trace: File | ArrayBuffer, onProgress?: () => void) {
    // TODO(hjd): This should probably also be a hash but that requires
    // trace processor support.
    const name = uuidv4();
    this.uploadedUrl = `https://storage.googleapis.com/${BUCKET_NAME}/${name}`;
    this.reqUrl =
      'https://www.googleapis.com/upload/storage/v1/b/' +
      `${BUCKET_NAME}/o?uploadType=media` +
      `&name=${name}&predefinedAcl=publicRead`;
    this.onProgress = onProgress || (() => {});
    this.req = new XMLHttpRequest();
    this.req.onabort = (e: ProgressEvent) => this.onRpcEvent(e);
    this.req.onerror = (e: ProgressEvent) => this.onRpcEvent(e);
    this.req.upload.onprogress = (e: ProgressEvent) => this.onRpcEvent(e);
    this.req.onloadend = (e: ProgressEvent) => this.onRpcEvent(e);
    this.req.open('POST', this.reqUrl);
    this.req.setRequestHeader('Content-Type', 'application/octet-stream');
    this.req.send(trace);
  }

  waitForCompletion(): Promise<void> {
    return this.donePromise;
  }

  abort() {
    if (this.state === 'UPLOADING') {
      this.req.abort();
    }
  }

  getEtaString() {
    let str = `${Math.ceil((100 * this.uploadedSize) / this.totalSize)}%`;
    str += ` (${(this.uploadedSize / 1e6).toFixed(2)} MB)`;
    const elapsed = (performance.now() - this.startTime) / 1000;
    const rate = this.uploadedSize / elapsed;
    const etaSecs = Math.round((this.totalSize - this.uploadedSize) / rate);
    str += ' - ETA: ' + Time.toTimecode(Time.fromSeconds(etaSecs)).dhhmmss;
    return str;
  }

  private onRpcEvent(e: ProgressEvent) {
    let done = false;
    switch (e.type) {
      case 'progress':
        this.uploadedSize = e.loaded;
        this.totalSize = e.total;
        break;
      case 'abort':
        this.state = 'ERROR';
        this.error = 'Upload aborted';
        break;
      case 'error':
        this.state = 'ERROR';
        this.error = `${this.req.status} - ${this.req.statusText}`;
        break;
      case 'loadend':
        done = true;
        if (this.req.status === 200) {
          this.state = 'UPLOADED';
        } else if (this.state === 'UPLOADING') {
          this.state = 'ERROR';
          this.error = `${this.req.status} - ${this.req.statusText}`;
        }
        break;
      default:
        return;
    }
    this.onProgress();
    if (done) {
      this.donePromise.resolve();
    }
  }
}

// Bigint's are not serializable using JSON.stringify, so we use a special
// object when serialising
export type SerializedBigint = {
  __kind: 'bigint';
  value: string;
};

// Check if a value looks like a serialized bigint
export function isSerializedBigint(value: unknown): value is SerializedBigint {
  if (value === null) {
    return false;
  }
  if (typeof value !== 'object') {
    return false;
  }
  if ('__kind' in value && 'value' in value) {
    return value.__kind === 'bigint' && isString(value.value);
  }
  return false;
}

export function serializeStateObject(object: unknown): string {
  const json = JSON.stringify(object, (key, value) => {
    if (typeof value === 'bigint') {
      return {
        __kind: 'bigint',
        value: value.toString(),
      };
    }
    return key === 'nonSerializableState' ? undefined : value;
  });
  return json;
}

export function deserializeStateObject<T>(json: string): T {
  const object = JSON.parse(json, (_key, value) => {
    if (isSerializedBigint(value)) {
      return BigInt(value.value);
    }
    return value;
  });
  return object as T;
}

export async function saveState(
  stateOrConfig: State | RecordConfig,
): Promise<string> {
  const text = serializeStateObject(stateOrConfig);
  const hash = await toSha256(text);
  const url =
    'https://www.googleapis.com/upload/storage/v1/b/' +
    `${BUCKET_NAME}/o?uploadType=media` +
    `&name=${hash}&predefinedAcl=publicRead`;
  const response = await fetch(url, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json; charset=utf-8',
    },
    body: text,
  });
  await response.json();
  return hash;
}

// This has a bug:
// x.toString(16) doesn't zero pad so if the digest is:
// [23, 7, 42, ...]
// You get:
// ['17', '7', '2a', ...] = 1772a...
// Rather than:
// ['17', '07', '2a', ...] = 17072a...
// As you ought to (and as the hexdigest is computed by e.g. Python).
// Unfortunately there are a lot of old permalinks out there so we
// still need this broken implementation to check their hashes.
export async function buggyToSha256(str: string): Promise<string> {
  const buffer = new TextEncoder().encode(str);
  const digest = await crypto.subtle.digest('SHA-256', buffer);
  return Array.from(new Uint8Array(digest))
    .map((x) => x.toString(16))
    .join('');
}

export async function toSha256(str: string): Promise<string> {
  const buffer = new TextEncoder().encode(str);
  const digest = await crypto.subtle.digest('SHA-256', buffer);
  return Array.from(new Uint8Array(digest))
    .map((x) => x.toString(16).padStart(2, '0'))
    .join('');
}
