// Copyright (C) 2019 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 {JsonRpc2, LikeSocket} from 'noice-json-rpc';

// To really understand how this works it is useful to see the implementation
// of noice-json-rpc.
export class DevToolsSocket implements LikeSocket {
  private messageCallback: Function = (_: string) => {};
  private openCallback: Function = () => {};
  private closeCallback: Function = () => {};
  private target: chrome.debugger.Debuggee|undefined;

  constructor() {
    chrome.debugger.onDetach.addListener(this.onDetach.bind(this));
    chrome.debugger.onEvent.addListener((_source, method, params) => {
      if (this.messageCallback) {
        const msg: JsonRpc2.Notification = {method, params};
        this.messageCallback(JSON.stringify(msg));
      }
    });
  }

  send(message: string): void {
    if (this.target === undefined) return;

    const msg: JsonRpc2.Request = JSON.parse(message);
    chrome.debugger.sendCommand(
        this.target, msg.method, msg.params, (result) => {
          if (result === undefined) result = {};
          const response: JsonRpc2.Response = {id: msg.id, result};
          this.messageCallback(JSON.stringify(response));
        });
  }

  // This method will be called once for each event soon after the creation of
  // this object. To understand better what happens, checking the implementation
  // of noice-json-rpc is very useful.
  // While the events "message" and "open" are for implementing the LikeSocket,
  // "close" is a callback set from ChromeTracingController, to reset the state
  // after a detach.
  on(event: string, cb: Function) {
    if (event === 'message') {
      this.messageCallback = cb;
    } else if (event === 'open') {
      this.openCallback = cb;
    } else if (event === 'close') {
      this.closeCallback = cb;
    }
  }

  removeListener(_event: string, _cb: Function) {
    throw new Error('Call unexpected');
  }

  attachToBrowser(then: (error?: string) => void) {
    this.attachToTarget({targetId: 'browser'}, then);
  }

  private attachToTarget(
      target: chrome.debugger.Debuggee, then: (error?: string) => void) {
    chrome.debugger.attach(target, /* requiredVersion=*/ '1.3', () => {
      if (chrome.runtime.lastError) {
        then(chrome.runtime.lastError.message);
        return;
      }
      this.target = target;
      this.openCallback();
      then();
    });
  }

  detach() {
    if (this.target === undefined) return;

    chrome.debugger.detach(this.target, () => {
      this.target = undefined;
    });
  }

  onDetach(_source: chrome.debugger.Debuggee, _reason: string) {
    if (_source === this.target) {
      this.target = undefined;
      this.closeCallback();
    }
  }

  isAttached(): boolean {
    return this.target !== undefined;
  }
}
