// Copyright (C) 2018 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 '../tracks/all_frontend';

import * as m from 'mithril';

import {forwardRemoteCalls} from '../base/remote';
import {loadPermalink, navigate} from '../common/actions';
import {State} from '../common/state';
import {TimeSpan} from '../common/time';
import {EnginePortAndId} from '../controller/engine';
import {
  createWasmEngine,
  destroyWasmEngine,
  warmupWasmEngine,
} from '../controller/wasm_engine_proxy';

import {globals, QuantizedLoad, ThreadDesc} from './globals';
import {HomePage} from './home_page';
import {ViewerPage} from './viewer_page';

/**
 * The API the main thread exposes to the controller.
 */
class FrontendApi {
  updateState(state: State) {
    globals.state = state;

    // If the visible time in the global state has been updated more recently
    // than the visible time handled by the frontend @ 60fps, update it. This
    // typically happens when restoring the state from a permalink.
    const vizTraceTime = globals.state.visibleTraceTime;
    if (vizTraceTime.lastUpdate >
        globals.frontendLocalState.visibleTimeLastUpdate) {
      globals.frontendLocalState.updateVisibleTime(
          new TimeSpan(vizTraceTime.startSec, vizTraceTime.endSec));
    }

    this.redraw();
  }

  // TODO: we can't have a publish method for each batch of data that we don't
  // want to keep in the global state. Figure out a more generic and type-safe
  // mechanism to achieve this.

  publishOverviewData(data: {[key: string]: QuantizedLoad}) {
    for (const key of Object.keys(data)) {
      if (!globals.overviewStore.has(key)) {
        globals.overviewStore.set(key, []);
      }
      globals.overviewStore.get(key)!.push(data[key]);
    }
    globals.rafScheduler.scheduleRedraw();
  }

  publishTrackData(args: {id: string, data: {}}) {
    globals.trackDataStore.set(args.id, args.data);
    globals.rafScheduler.scheduleRedraw();
  }

  publishQueryResult(args: {id: string, data: {}}) {
    globals.queryResults.set(args.id, args.data);
    this.redraw();
  }

  publishThreads(data: ThreadDesc[]) {
    globals.threads.clear();
    data.forEach(thread => {
      globals.threads.set(thread.utid, thread);
    });
    this.redraw();
  }

  /**
   * Creates a new trace processor wasm engine (backed by a worker running
   * engine_bundle.js) and returns a MessagePort for talking to it.
   * This indirection is due to workers not being able create workers in
   * Chrome which is tracked at: crbug.com/31666
   * TODO(hjd): Remove this once the fix has landed.
   */
  createEngine(): EnginePortAndId {
    const id = new Date().toUTCString();
    return {id, port: createWasmEngine(id)};
  }

  destroyEngine(id: string) {
    destroyWasmEngine(id);
  }

  private redraw(): void {
    if (globals.state.route && globals.state.route !== m.route.get()) {
      m.route.set(globals.state.route);
    } else {
      globals.rafScheduler.scheduleFullRedraw();
    }
  }
}

function main() {
  const controller = new Worker('controller_bundle.js');
  controller.onerror = e => {
    console.error(e);
  };
  const channel = new MessageChannel();
  forwardRemoteCalls(channel.port2, new FrontendApi());
  controller.postMessage(channel.port1, [channel.port1]);

  globals.initialize(controller.postMessage.bind(controller));

  warmupWasmEngine();

  m.route(document.body, '/', {
    '/': HomePage,
    '/viewer': ViewerPage,
  });

  // Put these variables in the global scope for better debugging.
  (window as {} as {m: {}}).m = m;
  (window as {} as {globals: {}}).globals = globals;

  // /?s=xxxx for permalinks.
  const stateHash = m.route.param('s');
  if (stateHash) {
    globals.dispatch(loadPermalink(stateHash));
  }

  // Prevent pinch zoom.
  document.body.addEventListener('wheel', (e: MouseEvent) => {
    if (e.ctrlKey) e.preventDefault();
  });

  globals.dispatch(navigate(m.route.get()));
}

main();
