/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

export default class RemoteObject {
  /**
   * This may not be an interface due to "instanceof SDK.RemoteObject" checks in the code.
   */

  /**
   * @param {*} value
   * @return {!RemoteObject}
   */
  static fromLocalObject(value) {
    return new LocalJSONObject(value);
  }

  /**
   * @param {!RemoteObject} remoteObject
   * @return {string}
   */
  static type(remoteObject) {
    if (remoteObject === null) {
      return 'null';
    }

    const type = typeof remoteObject;
    if (type !== 'object' && type !== 'function') {
      return type;
    }

    return remoteObject.type;
  }

  /**
   * @param {string} description
   * @return {string}
   */
  static arrayNameFromDescription(description) {
    return description.replace(_descriptionLengthParenRegex, '').replace(_descriptionLengthSquareRegex, '');
  }

  /**
   * @param {!RemoteObject|!Protocol.Runtime.RemoteObject|!Protocol.Runtime.ObjectPreview} object
   * @return {number}
   */
  static arrayLength(object) {
    if (object.subtype !== 'array' && object.subtype !== 'typedarray') {
      return 0;
    }
    // Array lengths in V8-generated descriptions switched from square brackets to parentheses.
    // Both formats are checked in case the front end is dealing with an old version of V8.
    const parenMatches = object.description.match(_descriptionLengthParenRegex);
    const squareMatches = object.description.match(_descriptionLengthSquareRegex);
    return parenMatches ? parseInt(parenMatches[1], 10) : (squareMatches ? parseInt(squareMatches[1], 10) : 0);
  }

  /**
   * @param {*} object
   * @return {?string}
   */
  static unserializableDescription(object) {
    const type = typeof object;
    if (type === 'number') {
      const description = String(object);
      if (object === 0 && 1 / object < 0) {
        return UnserializableNumber.Negative0;
      }
      if (description === UnserializableNumber.NaN || description === UnserializableNumber.Infinity ||
          description === UnserializableNumber.NegativeInfinity) {
        return description;
      }
    }
    if (type === 'bigint') {
      return object + 'n';
    }
    return null;
  }

  /**
   * @param {!Protocol.Runtime.RemoteObject|!RemoteObject|number|string|boolean|undefined|null|bigint} object
   * @return {!Protocol.Runtime.CallArgument}
   */
  static toCallArgument(object) {
    const type = typeof object;
    if (type === 'undefined') {
      return {};
    }
    const unserializableDescription = RemoteObject.unserializableDescription(object);
    if (type === 'number') {
      if (unserializableDescription !== null) {
        return {unserializableValue: unserializableDescription};
      }
      return {value: object};
    }
    if (type === 'bigint') {
      return {unserializableValue: /** @type {!Protocol.Runtime.UnserializableValue} */ (unserializableDescription)};
    }
    if (type === 'string' || type === 'boolean') {
      return {value: object};
    }

    if (!object) {
      return {value: null};
    }

    // The unserializableValue is a function on RemoteObject's and a simple property on
    // Protocol.Runtime.RemoteObject's.
    if (object instanceof RemoteObject) {
      const unserializableValue = object.unserializableValue();
      if (unserializableValue !== undefined) {
        return {unserializableValue: unserializableValue};
      }
    } else if (object.unserializableValue !== undefined) {
      return {unserializableValue: object.unserializableValue};
    }

    if (typeof object.objectId !== 'undefined') {
      return {objectId: object.objectId};
    }

    return {value: object.value};
  }

  /**
   * @param {!RemoteObject} object
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  static async loadFromObjectPerProto(object, generatePreview) {
    const result = await Promise.all([
      object.getAllProperties(true /* accessorPropertiesOnly */, generatePreview),
      object.getOwnProperties(generatePreview)
    ]);
    const accessorProperties = result[0].properties;
    const ownProperties = result[1].properties;
    const internalProperties = result[1].internalProperties;
    if (!ownProperties || !accessorProperties) {
      return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
    }
    const propertiesMap = new Map();
    const propertySymbols = [];
    for (let i = 0; i < accessorProperties.length; i++) {
      const property = accessorProperties[i];
      if (property.symbol) {
        propertySymbols.push(property);
      } else {
        propertiesMap.set(property.name, property);
      }
    }
    for (let i = 0; i < ownProperties.length; i++) {
      const property = ownProperties[i];
      if (property.isAccessorProperty()) {
        continue;
      }
      if (property.symbol) {
        propertySymbols.push(property);
      } else {
        propertiesMap.set(property.name, property);
      }
    }
    return {
      properties: propertiesMap.valuesArray().concat(propertySymbols),
      internalProperties: internalProperties ? internalProperties : null
    };
  }

  /**
   * @return {?Protocol.Runtime.CustomPreview}
   */
  customPreview() {
    return null;
  }

  /** @return {!Protocol.Runtime.RemoteObjectId|undefined} */
  get objectId() {
    return 'Not implemented';
  }

  /** @return {string} */
  get type() {
    throw 'Not implemented';
  }

  /** @return {string|undefined} */
  get subtype() {
    throw 'Not implemented';
  }

  /** @return {*} */
  get value() {
    throw 'Not implemented';
  }

  /** @return {string|undefined} */
  unserializableValue() {
    throw 'Not implemented';
  }

  /** @return {string|undefined} */
  get description() {
    throw 'Not implemented';
  }

  /** @return {boolean} */
  get hasChildren() {
    throw 'Not implemented';
  }

  /**
   * @return {!Protocol.Runtime.ObjectPreview|undefined}
   */
  get preview() {
    return undefined;
  }

  /**
   * @return {?string}
   */
  get className() {
    return null;
  }

  /**
   * @return {number}
   */
  arrayLength() {
    throw 'Not implemented';
  }

  /**
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  getOwnProperties(generatePreview) {
    throw 'Not implemented';
  }

  /**
   * @param {boolean} accessorPropertiesOnly
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  getAllProperties(accessorPropertiesOnly, generatePreview) {
    throw 'Not implemented';
  }

  /**
   * @param {!Protocol.Runtime.CallArgument} name
   * @return {!Promise<string|undefined>}
   */
  async deleteProperty(name) {
    throw 'Not implemented';
  }

  /**
   * @param {string|!Protocol.Runtime.CallArgument} name
   * @param {string} value
   * @return {!Promise<string|undefined>}
   */
  async setPropertyValue(name, value) {
    throw 'Not implemented';
  }

  /**
   * @param {function(this:Object, ...)} functionDeclaration
   * @param {!Array<!Protocol.Runtime.CallArgument>=} args
   * @return {!Promise<!SDK.CallFunctionResult>}
   */
  callFunction(functionDeclaration, args) {
    throw 'Not implemented';
  }

  /**
   * @param {function(this:Object, ...):T} functionDeclaration
   * @param {!Array<!Protocol.Runtime.CallArgument>|undefined} args
   * @return {!Promise<T>}
   * @template T
   */
  callFunctionJSON(functionDeclaration, args) {
    throw 'Not implemented';
  }

  release() {
  }

  /**
   * @return {!SDK.DebuggerModel}
   */
  debuggerModel() {
    throw new Error('DebuggerModel-less object');
  }

  /**
   * @return {!SDK.RuntimeModel}
   */
  runtimeModel() {
    throw new Error('RuntimeModel-less object');
  }

  /**
   * @return {boolean}
   */
  isNode() {
    return false;
  }
}

export class RemoteObjectImpl extends RemoteObject {
  /**
   * @param {!SDK.RuntimeModel} runtimeModel
   * @param {string|undefined} objectId
   * @param {string} type
   * @param {string|undefined} subtype
   * @param {*} value
   * @param {!Protocol.Runtime.UnserializableValue=} unserializableValue
   * @param {string=} description
   * @param {!Protocol.Runtime.ObjectPreview=} preview
   * @param {!Protocol.Runtime.CustomPreview=} customPreview
   * @param {string=} className
   */
  constructor(
      runtimeModel, objectId, type, subtype, value, unserializableValue, description, preview, customPreview,
      className) {
    super();

    this._runtimeModel = runtimeModel;
    this._runtimeAgent = runtimeModel.target().runtimeAgent();

    this._type = type;
    this._subtype = subtype;
    if (objectId) {
      // handle
      this._objectId = objectId;
      this._description = description;
      this._hasChildren = (type !== 'symbol');
      this._preview = preview;
    } else {
      this._description = description;
      if (!this.description && unserializableValue) {
        this._description = unserializableValue;
      }
      if (!this._description && (typeof value !== 'object' || value === null)) {
        this._description = value + '';
      }
      this._hasChildren = false;
      if (typeof unserializableValue === 'string') {
        this._unserializableValue = unserializableValue;
        if (unserializableValue === UnserializableNumber.Infinity ||
            unserializableValue === UnserializableNumber.NegativeInfinity ||
            unserializableValue === UnserializableNumber.Negative0 ||
            unserializableValue === UnserializableNumber.NaN) {
          this._value = Number(unserializableValue);
        } else if (type === 'bigint' && unserializableValue.endsWith('n')) {
          this._value = BigInt(unserializableValue.substring(0, unserializableValue.length - 1));
        } else {
          this._value = unserializableValue;
        }

      } else {
        this._value = value;
      }
    }
    this._customPreview = customPreview || null;
    this._className = typeof className === 'string' ? className : null;
  }

  /**
   * @override
   * @return {?Protocol.Runtime.CustomPreview}
   */
  customPreview() {
    return this._customPreview;
  }

  /**
   * @override
   * @return {!Protocol.Runtime.RemoteObjectId|undefined}
   */
  get objectId() {
    return this._objectId;
  }

  /**
   * @override
   * @return {string}
   */
  get type() {
    return this._type;
  }

  /**
   * @override
   * @return {string|undefined}
   */
  get subtype() {
    return this._subtype;
  }

  /**
   * @override
   * @return {*}
   */
  get value() {
    return this._value;
  }

  /**
   * @override
   * @return {string|undefined}
   */
  unserializableValue() {
    return this._unserializableValue;
  }

  /**
   * @override
   * @return {string|undefined}
   */
  get description() {
    return this._description;
  }

  /**
   * @override
   * @return {boolean}
   */
  get hasChildren() {
    return this._hasChildren;
  }

  /**
   * @override
   * @return {!Protocol.Runtime.ObjectPreview|undefined}
   */
  get preview() {
    return this._preview;
  }

  /**
   * @override
   * @return {?string}
   */
  get className() {
    return this._className;
  }

  /**
   * @override
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  getOwnProperties(generatePreview) {
    return this.doGetProperties(true, false, generatePreview);
  }

  /**
   * @override
   * @param {boolean} accessorPropertiesOnly
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  getAllProperties(accessorPropertiesOnly, generatePreview) {
    return this.doGetProperties(false, accessorPropertiesOnly, generatePreview);
  }

  /**
   * @param {boolean} ownProperties
   * @param {boolean} accessorPropertiesOnly
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  async doGetProperties(ownProperties, accessorPropertiesOnly, generatePreview) {
    if (!this._objectId) {
      return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
    }

    const response = await this._runtimeAgent.invoke_getProperties(
        {objectId: this._objectId, ownProperties, accessorPropertiesOnly, generatePreview});
    if (response[Protocol.Error]) {
      return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
    }
    if (response.exceptionDetails) {
      this._runtimeModel.exceptionThrown(Date.now(), response.exceptionDetails);
      return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
    }
    const {result: properties = [], internalProperties = [], privateProperties = []} = response;
    const result = [];
    for (const property of properties) {
      const propertyValue = property.value ? this._runtimeModel.createRemoteObject(property.value) : null;
      const propertySymbol = property.symbol ? this._runtimeModel.createRemoteObject(property.symbol) : null;
      const remoteProperty = new RemoteObjectProperty(
          property.name, propertyValue, !!property.enumerable, !!property.writable, !!property.isOwn,
          !!property.wasThrown, propertySymbol);

      if (typeof property.value === 'undefined') {
        if (property.get && property.get.type !== 'undefined') {
          remoteProperty.getter = this._runtimeModel.createRemoteObject(property.get);
        }
        if (property.set && property.set.type !== 'undefined') {
          remoteProperty.setter = this._runtimeModel.createRemoteObject(property.set);
        }
      }
      result.push(remoteProperty);
    }
    for (const property of privateProperties) {
      const propertyValue = this._runtimeModel.createRemoteObject(property.value);
      const remoteProperty = new RemoteObjectProperty(
          property.name, propertyValue, true, true, true, false, undefined, false, undefined, true);
      result.push(remoteProperty);
    }

    const internalPropertiesResult = [];
    for (const property of internalProperties) {
      if (!property.value) {
        continue;
      }
      if (property.name === '[[StableObjectId]]') {
        continue;
      }
      const propertyValue = this._runtimeModel.createRemoteObject(property.value);
      internalPropertiesResult.push(
          new RemoteObjectProperty(property.name, propertyValue, true, false, undefined, undefined, undefined, true));
    }
    return {properties: result, internalProperties: internalPropertiesResult};
  }

  /**
   * @override
   * @param {string|!Protocol.Runtime.CallArgument} name
   * @param {string} value
   * @return {!Promise<string|undefined>}
   */
  async setPropertyValue(name, value) {
    if (!this._objectId) {
      return `Can't set a property of non-object.`;
    }

    const response = await this._runtimeAgent.invoke_evaluate({expression: value, silent: true});
    if (response[Protocol.Error] || response.exceptionDetails) {
      return response[Protocol.Error] ||
          (response.result.type !== 'string' ? response.result.description :
                                               /** @type {string} */ (response.result.value));
    }

    if (typeof name === 'string') {
      name = RemoteObject.toCallArgument(name);
    }

    const resultPromise = this.doSetObjectPropertyValue(response.result, name);

    if (response.result.objectId) {
      this._runtimeAgent.releaseObject(response.result.objectId);
    }

    return resultPromise;
  }

  /**
   * @param {!Protocol.Runtime.RemoteObject} result
   * @param {!Protocol.Runtime.CallArgument} name
   * @return {!Promise<string|undefined>}
   */
  async doSetObjectPropertyValue(result, name) {
    // This assignment may be for a regular (data) property, and for an accessor property (with getter/setter).
    // Note the sensitive matter about accessor property: the property may be physically defined in some proto object,
    // but logically it is bound to the object in question. JavaScript passes this object to getters/setters, not the object
    // where property was defined; so do we.
    const setPropertyValueFunction = 'function(a, b) { this[a] = b; }';

    const argv = [name, RemoteObject.toCallArgument(result)];
    const response = await this._runtimeAgent.invoke_callFunctionOn(
        {objectId: this._objectId, functionDeclaration: setPropertyValueFunction, arguments: argv, silent: true});
    const error = response[Protocol.Error];
    return error || response.exceptionDetails ? error || response.result.description : undefined;
  }

  /**
   * @override
   * @param {!Protocol.Runtime.CallArgument} name
   * @return {!Promise<string|undefined>}
   */
  async deleteProperty(name) {
    if (!this._objectId) {
      return `Can't delete a property of non-object.`;
    }

    const deletePropertyFunction = 'function(a) { delete this[a]; return !(a in this); }';
    const response = await this._runtimeAgent.invoke_callFunctionOn(
        {objectId: this._objectId, functionDeclaration: deletePropertyFunction, arguments: [name], silent: true});

    if (response[Protocol.Error] || response.exceptionDetails) {
      return response[Protocol.Error] || response.result.description;
    }

    if (!response.result.value) {
      return 'Failed to delete property.';
    }
  }

  /**
   * @override
   * @param {function(this:Object, ...)} functionDeclaration
   * @param {!Array<!Protocol.Runtime.CallArgument>=} args
   * @return {!Promise<!SDK.CallFunctionResult>}
   */
  async callFunction(functionDeclaration, args) {
    const response = await this._runtimeAgent.invoke_callFunctionOn(
        {objectId: this._objectId, functionDeclaration: functionDeclaration.toString(), arguments: args, silent: true});
    if (response[Protocol.Error]) {
      return {object: null, wasThrown: false};
    }
    // TODO: release exceptionDetails object
    return {object: this._runtimeModel.createRemoteObject(response.result), wasThrown: !!response.exceptionDetails};
  }

  /**
   * @override
   * @param {function(this:Object, ...):T} functionDeclaration
   * @param {!Array<!Protocol.Runtime.CallArgument>|undefined} args
   * @return {!Promise<T>}
   * @template T
   */
  async callFunctionJSON(functionDeclaration, args) {
    const response = await this._runtimeAgent.invoke_callFunctionOn({
      objectId: this._objectId,
      functionDeclaration: functionDeclaration.toString(),
      arguments: args,
      silent: true,
      returnByValue: true
    });
    return response[Protocol.Error] || response.exceptionDetails ? null : response.result.value;
  }

  /**
   * @override
   */
  release() {
    if (!this._objectId) {
      return;
    }
    this._runtimeAgent.releaseObject(this._objectId);
  }

  /**
   * @override
   * @return {number}
   */
  arrayLength() {
    return RemoteObject.arrayLength(this);
  }

  /**
   * @override
   * @return {!SDK.DebuggerModel}
   */
  debuggerModel() {
    return this._runtimeModel.debuggerModel();
  }

  /**
   * @override
   * @return {!SDK.RuntimeModel}
   */
  runtimeModel() {
    return this._runtimeModel;
  }

  /**
   * @override
   * @return {boolean}
   */
  isNode() {
    return !!this._objectId && this.type === 'object' && this.subtype === 'node';
  }
}

export class ScopeRemoteObject extends RemoteObjectImpl {
  /**
   * @param {!SDK.RuntimeModel} runtimeModel
   * @param {string|undefined} objectId
   * @param {!ScopeRef} scopeRef
   * @param {string} type
   * @param {string|undefined} subtype
   * @param {*} value
   * @param {!Protocol.Runtime.UnserializableValue=} unserializableValue
   * @param {string=} description
   * @param {!Protocol.Runtime.ObjectPreview=} preview
   */
  constructor(runtimeModel, objectId, scopeRef, type, subtype, value, unserializableValue, description, preview) {
    super(runtimeModel, objectId, type, subtype, value, unserializableValue, description, preview);
    this._scopeRef = scopeRef;
    this._savedScopeProperties = undefined;
  }

  /**
   * @override
   * @param {boolean} ownProperties
   * @param {boolean} accessorPropertiesOnly
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  async doGetProperties(ownProperties, accessorPropertiesOnly, generatePreview) {
    if (accessorPropertiesOnly) {
      return /** @type {!SDK.GetPropertiesResult} */ ({properties: [], internalProperties: []});
    }

    if (this._savedScopeProperties) {
      // No need to reload scope variables, as the remote object never
      // changes its properties. If variable is updated, the properties
      // array is patched locally.
      return {properties: this._savedScopeProperties.slice(), internalProperties: null};
    }

    const allProperties =
        await super.doGetProperties(ownProperties, accessorPropertiesOnly, true /* generatePreview */);
    if (this._scopeRef && Array.isArray(allProperties.properties)) {
      this._savedScopeProperties = allProperties.properties.slice();
      if (!this._scopeRef.callFrameId) {
        for (const property of this._savedScopeProperties) {
          property.writable = false;
        }
      }
    }
    return allProperties;
  }

  /**
   * @override
   * @param {!Protocol.Runtime.RemoteObject} result
   * @param {!Protocol.Runtime.CallArgument} argumentName
   * @return {!Promise<string|undefined>}
   */
  async doSetObjectPropertyValue(result, argumentName) {
    const name = /** @type {string} */ (argumentName.value);
    const error = await this.debuggerModel().setVariableValue(
        this._scopeRef.number, name, RemoteObject.toCallArgument(result), this._scopeRef.callFrameId);
    if (error) {
      return error;
    }
    if (this._savedScopeProperties) {
      for (const property of this._savedScopeProperties) {
        if (property.name === name) {
          property.value = this._runtimeModel.createRemoteObject(result);
        }
      }
    }
  }
}

export class ScopeRef {
  /**
   * @param {number} number
   * @param {string=} callFrameId
   */
  constructor(number, callFrameId) {
    this.number = number;
    this.callFrameId = callFrameId;
  }
}

/**
 * @unrestricted
 */
export class RemoteObjectProperty {
  /**
   * @param {string} name
   * @param {?RemoteObject} value
   * @param {boolean=} enumerable
   * @param {boolean=} writable
   * @param {boolean=} isOwn
   * @param {boolean=} wasThrown
   * @param {?RemoteObject=} symbol
   * @param {boolean=} synthetic
   * @param {function(string):!Promise<?RemoteObject>=} syntheticSetter
   * @param {boolean=} isPrivate
   */
  constructor(name, value, enumerable, writable, isOwn, wasThrown, symbol, synthetic, syntheticSetter, isPrivate) {
    this.name = name;
    if (value !== null) {
      this.value = value;
    }
    this.enumerable = typeof enumerable !== 'undefined' ? enumerable : true;
    const isNonSyntheticOrSyntheticWritable = !synthetic || !!syntheticSetter;
    this.writable = typeof writable !== 'undefined' ? writable : isNonSyntheticOrSyntheticWritable;
    this.isOwn = !!isOwn;
    this.wasThrown = !!wasThrown;
    if (symbol) {
      this.symbol = symbol;
    }
    this.synthetic = !!synthetic;
    if (syntheticSetter) {
      this.syntheticSetter = syntheticSetter;
    }
    this.private = !!isPrivate;
  }

  /**
   * @param {string} expression
   * @return {!Promise<boolean>}
   */
  async setSyntheticValue(expression) {
    if (!this.syntheticSetter) {
      return false;
    }
    const result = await this.syntheticSetter(expression);
    if (result) {
      this.value = result;
    }
    return !!result;
  }

  /**
   * @return {boolean}
   */
  isAccessorProperty() {
    return !!(this.getter || this.setter);
  }
}

// Below is a wrapper around a local object that implements the RemoteObject interface,
// which can be used by the UI code (primarily ObjectPropertiesSection).
// Note that only JSON-compliant objects are currently supported, as there's no provision
// for traversing prototypes, extracting class names via constructor, handling properties
// or functions.

export class LocalJSONObject extends RemoteObject {
  /**
   * @param {*} value
   */
  constructor(value) {
    super();
    this._value = value;
    /** @type {string} */
    this._cachedDescription;
    /** @type {!Array<!RemoteObjectProperty>} */
    this._cachedChildren;
  }

  /**
   * @override
   * @return {!Protocol.Runtime.RemoteObjectId|undefined}
   * */
  get objectId() {
    return undefined;
  }

  /**
   * @override
   * @return {*}
   */
  get value() {
    return this._value;
  }

  /**
   * @override
   * @return {string|undefined}
   */
  unserializableValue() {
    const unserializableDescription = RemoteObject.unserializableDescription(this._value);
    return unserializableDescription || undefined;
  }

  /**
   * @override
   * @return {string}
   */
  get description() {
    if (this._cachedDescription) {
      return this._cachedDescription;
    }

    /**
     * @param {!RemoteObjectProperty} property
     * @return {string}
     * @this {LocalJSONObject}
     */
    function formatArrayItem(property) {
      return this._formatValue(property.value);
    }

    /**
     * @param {!RemoteObjectProperty} property
     * @return {string}
     * @this {LocalJSONObject}
     */
    function formatObjectItem(property) {
      let name = property.name;
      if (/^\s|\s$|^$|\n/.test(name)) {
        name = '"' + name.replace(/\n/g, '\u21B5') + '"';
      }
      return name + ': ' + this._formatValue(property.value);
    }

    if (this.type === 'object') {
      switch (this.subtype) {
        case 'array':
          this._cachedDescription = this._concatenate('[', ']', formatArrayItem.bind(this));
          break;
        case 'date':
          this._cachedDescription = '' + this._value;
          break;
        case 'null':
          this._cachedDescription = 'null';
          break;
        default:
          this._cachedDescription = this._concatenate('{', '}', formatObjectItem.bind(this));
      }
    } else {
      this._cachedDescription = String(this._value);
    }

    return this._cachedDescription;
  }

  /**
   * @param {?RemoteObject} value
   * @return {string}
   */
  _formatValue(value) {
    if (!value) {
      return 'undefined';
    }
    const description = value.description || '';
    if (value.type === 'string') {
      return '"' + description.replace(/\n/g, '\u21B5') + '"';
    }
    return description;
  }

  /**
   * @param {string} prefix
   * @param {string} suffix
   * @param {function(!RemoteObjectProperty)} formatProperty
   * @return {string}
   */
  _concatenate(prefix, suffix, formatProperty) {
    const previewChars = 100;

    let buffer = prefix;
    const children = this._children();
    for (let i = 0; i < children.length; ++i) {
      const itemDescription = formatProperty(children[i]);
      if (buffer.length + itemDescription.length > previewChars) {
        buffer += ',\u2026';
        break;
      }
      if (i) {
        buffer += ', ';
      }
      buffer += itemDescription;
    }
    buffer += suffix;
    return buffer;
  }

  /**
   * @override
   * @return {string}
   */
  get type() {
    return typeof this._value;
  }

  /**
   * @override
   * @return {string|undefined}
   */
  get subtype() {
    if (this._value === null) {
      return 'null';
    }

    if (Array.isArray(this._value)) {
      return 'array';
    }

    if (this._value instanceof Date) {
      return 'date';
    }

    return undefined;
  }

  /**
   * @override
   * @return {boolean}
   */
  get hasChildren() {
    if ((typeof this._value !== 'object') || (this._value === null)) {
      return false;
    }
    return !!Object.keys(/** @type {!Object} */ (this._value)).length;
  }

  /**
   * @override
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  getOwnProperties(generatePreview) {
    return Promise.resolve(
        /** @type {!SDK.GetPropertiesResult} */ ({properties: this._children(), internalProperties: null}));
  }

  /**
   * @override
   * @param {boolean} accessorPropertiesOnly
   * @param {boolean} generatePreview
   * @return {!Promise<!SDK.GetPropertiesResult>}
   */
  getAllProperties(accessorPropertiesOnly, generatePreview) {
    if (accessorPropertiesOnly) {
      return Promise.resolve(/** @type {!SDK.GetPropertiesResult} */ ({properties: [], internalProperties: null}));
    } else {
      return Promise.resolve(
          /** @type {!SDK.GetPropertiesResult} */ ({properties: this._children(), internalProperties: null}));
    }
  }

  /**
   * @return {!Array.<!RemoteObjectProperty>}
   */
  _children() {
    if (!this.hasChildren) {
      return [];
    }
    const value = /** @type {!Object} */ (this._value);

    /**
     * @param {string} propName
     * @return {!RemoteObjectProperty}
     */
    function buildProperty(propName) {
      let propValue = value[propName];
      if (!(propValue instanceof RemoteObject)) {
        propValue = RemoteObject.fromLocalObject(propValue);
      }
      return new RemoteObjectProperty(propName, propValue);
    }
    if (!this._cachedChildren) {
      this._cachedChildren = Object.keys(value).map(buildProperty);
    }
    return this._cachedChildren;
  }

  /**
   * @override
   * @return {number}
   */
  arrayLength() {
    return Array.isArray(this._value) ? this._value.length : 0;
  }

  /**
   * @override
   * @param {function(this:Object, ...)} functionDeclaration
   * @param {!Array<!Protocol.Runtime.CallArgument>=} args
   * @return {!Promise<!SDK.CallFunctionResult>}
   */
  callFunction(functionDeclaration, args) {
    const target = /** @type {?Object} */ (this._value);
    const rawArgs = args ? args.map(arg => arg.value) : [];

    let result;
    let wasThrown = false;
    try {
      result = functionDeclaration.apply(target, rawArgs);
    } catch (e) {
      wasThrown = true;
    }

    const object = RemoteObject.fromLocalObject(result);

    return Promise.resolve(
        /** @type {!SDK.CallFunctionResult} */ ({object, wasThrown}));
  }

  /**
   * @override
   * @param {function(this:Object, ...):T} functionDeclaration
   * @param {!Array<!Protocol.Runtime.CallArgument>|undefined} args
   * @return {!Promise<T>}
   * @template T
   */
  callFunctionJSON(functionDeclaration, args) {
    const target = /** @type {?Object} */ (this._value);
    const rawArgs = args ? args.map(arg => arg.value) : [];

    let result;
    try {
      result = functionDeclaration.apply(target, rawArgs);
    } catch (e) {
      result = null;
    }

    return Promise.resolve(result);
  }
}

export class RemoteArray {
  /**
   * @param {!RemoteObject} object
   */
  constructor(object) {
    this._object = object;
  }

  /**
   * @param {?RemoteObject} object
   * @return {!RemoteArray}
   */
  static objectAsArray(object) {
    if (!object || object.type !== 'object' || (object.subtype !== 'array' && object.subtype !== 'typedarray')) {
      throw new Error('Object is empty or not an array');
    }
    return new RemoteArray(object);
  }

  /**
   * @param {!Array<!RemoteObject>} objects
   * @return {!Promise<!RemoteArray>}
   */
  static createFromRemoteObjects(objects) {
    if (!objects.length) {
      throw new Error('Input array is empty');
    }
    const objectArguments = [];
    for (let i = 0; i < objects.length; ++i) {
      objectArguments.push(RemoteObject.toCallArgument(objects[i]));
    }
    return objects[0].callFunction(createArray, objectArguments).then(returnRemoteArray);

    /**
     * @return {!Array<*>}
     */
    function createArray() {
      if (arguments.length > 1) {
        return new Array(arguments);
      }
      return [arguments[0]];
    }

    /**
     * @param {!SDK.CallFunctionResult} result
     * @return {!RemoteArray}
     */
    function returnRemoteArray(result) {
      if (result.wasThrown || !result.object) {
        throw new Error('Call function throws exceptions or returns empty value');
      }
      return RemoteArray.objectAsArray(result.object);
    }
  }

  /**
   * @param {number} index
   * @return {!Promise<!RemoteObject>}
   */
  at(index) {
    if (index < 0 || index > this._object.arrayLength()) {
      throw new Error('Out of range');
    }
    return this._object.callFunction(at, [RemoteObject.toCallArgument(index)]).then(assertCallFunctionResult);

    /**
     * @suppressReceiverCheck
     * @param {number} index
     * @return {*}
     * @this {!Object}
     */
    function at(index) {
      return this[index];
    }

    /**
     * @param {!SDK.CallFunctionResult} result
     * @return {!RemoteObject}
     */
    function assertCallFunctionResult(result) {
      if (result.wasThrown || !result.object) {
        throw new Error('Exception in callFunction or result value is empty');
      }
      return result.object;
    }
  }

  /**
   * @return {number}
   */
  length() {
    return this._object.arrayLength();
  }

  /**
   * @param {function(!RemoteObject):!Promise<T>} func
   * @return {!Promise<!Array<T>>}
   * @template T
   */
  map(func) {
    const promises = [];
    for (let i = 0; i < this.length(); ++i) {
      promises.push(this.at(i).then(func));
    }
    return Promise.all(promises);
  }

  /**
   * @return {!RemoteObject}
   */
  object() {
    return this._object;
  }
}

export class RemoteFunction {
  /**
   * @param {!RemoteObject} object
   */
  constructor(object) {
    this._object = object;
  }

  /**
   * @param {?RemoteObject} object
   * @return {!RemoteFunction}
   */
  static objectAsFunction(object) {
    if (!object || object.type !== 'function') {
      throw new Error('Object is empty or not a function');
    }
    return new RemoteFunction(object);
  }

  /**
   * @return {!Promise<!RemoteObject>}
   */
  targetFunction() {
    return this._object.getOwnProperties(false /* generatePreview */).then(targetFunction.bind(this));

    /**
     * @param {!SDK.GetPropertiesResult} ownProperties
     * @return {!RemoteObject}
     * @this {RemoteFunction}
     */
    function targetFunction(ownProperties) {
      if (!ownProperties.internalProperties) {
        return this._object;
      }
      const internalProperties = ownProperties.internalProperties;
      for (const property of internalProperties) {
        if (property.name === '[[TargetFunction]]') {
          return property.value;
        }
      }
      return this._object;
    }
  }

  /**
   * @return {!Promise<?SDK.DebuggerModel.FunctionDetails>}
   */
  targetFunctionDetails() {
    return this.targetFunction().then(functionDetails.bind(this));

    /**
     * @param {!RemoteObject} targetFunction
     * @return {!Promise<?SDK.DebuggerModel.FunctionDetails>}
     * @this {RemoteFunction}
     */
    function functionDetails(targetFunction) {
      const boundReleaseFunctionDetails =
          releaseTargetFunction.bind(null, this._object !== targetFunction ? targetFunction : null);
      return targetFunction.debuggerModel().functionDetailsPromise(targetFunction).then(boundReleaseFunctionDetails);
    }

    /**
     * @param {?RemoteObject} targetFunction
     * @param {?SDK.DebuggerModel.FunctionDetails} functionDetails
     * @return {?SDK.DebuggerModel.FunctionDetails}
     */
    function releaseTargetFunction(targetFunction, functionDetails) {
      if (targetFunction) {
        targetFunction.release();
      }
      return functionDetails;
    }
  }

  /**
   * @return {!RemoteObject}
   */
  object() {
    return this._object;
  }
}

/**
 * @const
 * @type {!RegExp}
 */
const _descriptionLengthParenRegex = /\(([0-9]+)\)/;

/**
 * @const
 * @type {!RegExp}
 */
const _descriptionLengthSquareRegex = /\[([0-9]+)\]/;

/**
 * @const
 * @enum {!Protocol.Runtime.UnserializableValue}
 */
const UnserializableNumber = {
  Negative0: /** @type {!Protocol.Runtime.UnserializableValue} */ ('-0'),
  NaN: /** @type {!Protocol.Runtime.UnserializableValue} */ ('NaN'),
  Infinity: /** @type {!Protocol.Runtime.UnserializableValue} */ ('Infinity'),
  NegativeInfinity: /** @type {!Protocol.Runtime.UnserializableValue} */ ('-Infinity')
};

/* Legacy exported object */
self.SDK = self.SDK || {};

/* Legacy exported object */
SDK = SDK || {};

/** @constructor */
SDK.RemoteObject = RemoteObject;

/** @constructor */
SDK.RemoteObjectImpl = RemoteObjectImpl;

/** @constructor */
SDK.ScopeRemoteObject = ScopeRemoteObject;

/** @constructor */
SDK.ScopeRef = ScopeRef;

/** @constructor */
SDK.RemoteObjectProperty = RemoteObjectProperty;

/** @constructor */
SDK.LocalJSONObject = LocalJSONObject;

/** @constructor */
SDK.RemoteArray = RemoteArray;

/** @constructor */
SDK.RemoteFunction = RemoteFunction;

/**
 * @typedef {{object: ?RemoteObject, wasThrown: (boolean|undefined)}}
 */
SDK.CallFunctionResult;

/**
 * @typedef {{properties: ?Array<!RemoteObjectProperty>, internalProperties: ?Array<!RemoteObjectProperty>}}
 */
SDK.GetPropertiesResult;
