/*
 * Copyright (C) 2012 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.
 */
/**
 * @implements {Bindings.DebuggerSourceMapping}
 * @unrestricted
 */
Bindings.ResourceScriptMapping = class {
  /**
   * @param {!SDK.DebuggerModel} debuggerModel
   * @param {!Workspace.Workspace} workspace
   * @param {!Bindings.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
   */
  constructor(debuggerModel, workspace, debuggerWorkspaceBinding) {
    this._debuggerModel = debuggerModel;
    this._workspace = workspace;
    this._debuggerWorkspaceBinding = debuggerWorkspaceBinding;
    /** @type {!Map.<!Workspace.UISourceCode, !Bindings.ResourceScriptFile>} */
    this._uiSourceCodeToScriptFile = new Map();

    /** @type {!Map<string, !Bindings.ContentProviderBasedProject>} */
    this._projects = new Map();

    /** @type {!Set<!SDK.Script>} */
    this._acceptedScripts = new Set();
    const runtimeModel = debuggerModel.runtimeModel();
    this._eventListeners = [
      this._debuggerModel.addEventListener(SDK.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this),
      this._debuggerModel.addEventListener(
          SDK.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this),
      this._debuggerModel.addEventListener(
          SDK.DebuggerModel.Events.GlobalObjectCleared, this._globalObjectCleared, this),
      runtimeModel.addEventListener(
          SDK.RuntimeModel.Events.ExecutionContextDestroyed, this._executionContextDestroyed, this),
    ];
  }

  /**
   * @param {!SDK.Script} script
   * @return {!Bindings.ContentProviderBasedProject}
   */
  _project(script) {
    const frameId = script[Bindings.ResourceScriptMapping._frameIdSymbol];
    const prefix = script.isContentScript() ? 'js:extensions:' : 'js::';
    const projectId = prefix + this._debuggerModel.target().id() + ':' + frameId;
    let project = this._projects.get(projectId);
    if (!project) {
      const projectType =
          script.isContentScript() ? Workspace.projectTypes.ContentScripts : Workspace.projectTypes.Network;
      project = new Bindings.ContentProviderBasedProject(
          this._workspace, projectId, projectType, '' /* displayName */, false /* isServiceProject */);
      Bindings.NetworkProject.setTargetForProject(project, this._debuggerModel.target());
      this._projects.set(projectId, project);
    }
    return project;
  }

  /**
   * @override
   * @param {!SDK.DebuggerModel.Location} rawLocation
   * @return {?Workspace.UILocation}
   */
  rawLocationToUILocation(rawLocation) {
    const script = rawLocation.script();
    if (!script)
      return null;
    const project = this._project(script);
    const uiSourceCode = project.uiSourceCodeForURL(script.sourceURL);
    if (!uiSourceCode)
      return null;
    const scriptFile = this._uiSourceCodeToScriptFile.get(uiSourceCode);
    if (!scriptFile)
      return null;
    if ((scriptFile.hasDivergedFromVM() && !scriptFile.isMergingToVM()) || scriptFile.isDivergingFromVM())
      return null;
    if (!scriptFile._hasScripts([script]))
      return null;
    const lineNumber = rawLocation.lineNumber - (script.isInlineScriptWithSourceURL() ? script.lineOffset : 0);
    let columnNumber = rawLocation.columnNumber || 0;
    if (script.isInlineScriptWithSourceURL() && !lineNumber && columnNumber)
      columnNumber -= script.columnOffset;
    return uiSourceCode.uiLocation(lineNumber, columnNumber);
  }

  /**
   * @override
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?SDK.DebuggerModel.Location}
   */
  uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber) {
    const scriptFile = this._uiSourceCodeToScriptFile.get(uiSourceCode);
    if (!scriptFile)
      return null;
    const script = scriptFile._script;
    if (script.isInlineScriptWithSourceURL()) {
      return this._debuggerModel.createRawLocation(
          script, lineNumber + script.lineOffset, lineNumber ? columnNumber : columnNumber + script.columnOffset);
    }
    return this._debuggerModel.createRawLocation(script, lineNumber, columnNumber);
  }

  /**
   * @param {!SDK.Script} script
   * @return {boolean}
   */
  _acceptsScript(script) {
    if (!script.sourceURL || script.isLiveEdit() || (script.isInlineScript() && !script.hasSourceURL))
      return false;
    // Filter out embedder injected content scripts.
    if (script.isContentScript() && !script.hasSourceURL) {
      const parsedURL = new Common.ParsedURL(script.sourceURL);
      if (!parsedURL.isValid)
        return false;
    }
    return true;
  }

  /**
   * @param {!Common.Event} event
   */
  _parsedScriptSource(event) {
    const script = /** @type {!SDK.Script} */ (event.data);
    if (!this._acceptsScript(script))
      return;
    this._acceptedScripts.add(script);
    const originalContentProvider = script.originalContentProvider();
    const frameId = Bindings.frameIdForScript(script);
    script[Bindings.ResourceScriptMapping._frameIdSymbol] = frameId;

    const url = script.sourceURL;
    const project = this._project(script);

    // Remove previous UISourceCode, if any
    const oldUISourceCode = project.uiSourceCodeForURL(url);
    if (oldUISourceCode) {
      const scriptFile = this._uiSourceCodeToScriptFile.get(oldUISourceCode);
      this._removeScript(scriptFile._script);
    }

    // Create UISourceCode.
    const uiSourceCode = project.createUISourceCode(url, originalContentProvider.contentType());
    Bindings.NetworkProject.setInitialFrameAttribution(uiSourceCode, frameId);
    const metadata = Bindings.metadataForURL(this._debuggerModel.target(), frameId, url);

    // Bind UISourceCode to scripts.
    const scriptFile = new Bindings.ResourceScriptFile(this, uiSourceCode, [script]);
    this._uiSourceCodeToScriptFile.set(uiSourceCode, scriptFile);

    project.addUISourceCodeWithProvider(uiSourceCode, originalContentProvider, metadata, 'text/javascript');
    this._debuggerWorkspaceBinding.updateLocations(script);
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {?Bindings.ResourceScriptFile}
   */
  scriptFile(uiSourceCode) {
    return this._uiSourceCodeToScriptFile.get(uiSourceCode) || null;
  }

  /**
   * @param {!SDK.Script} script
   */
  _removeScript(script) {
    if (!this._acceptedScripts.has(script))
      return;
    this._acceptedScripts.delete(script);
    const project = this._project(script);
    const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (project.uiSourceCodeForURL(script.sourceURL));
    const scriptFile = this._uiSourceCodeToScriptFile.get(uiSourceCode);
    scriptFile.dispose();
    this._uiSourceCodeToScriptFile.delete(uiSourceCode);
    project.removeFile(script.sourceURL);
    this._debuggerWorkspaceBinding.updateLocations(script);
  }

  /**
   * @param {!Common.Event} event
   */
  _executionContextDestroyed(event) {
    const executionContext = /** @type {!SDK.ExecutionContext} */ (event.data);
    const scripts = this._debuggerModel.scriptsForExecutionContext(executionContext);
    for (const script of scripts)
      this._removeScript(script);
  }

  /**
   * @param {!Common.Event} event
   */
  _globalObjectCleared(event) {
    const scripts = Array.from(this._acceptedScripts);
    for (const script of scripts)
      this._removeScript(script);
  }

  resetForTest() {
    const scripts = Array.from(this._acceptedScripts);
    for (const script of scripts)
      this._removeScript(script);
  }

  dispose() {
    Common.EventTarget.removeEventListeners(this._eventListeners);
    const scripts = Array.from(this._acceptedScripts);
    for (const script of scripts)
      this._removeScript(script);
    for (const project of this._projects.values())
      project.removeProject();
    this._projects.clear();
  }
};

/**
 * @unrestricted
 */
Bindings.ResourceScriptFile = class extends Common.Object {
  /**
   * @param {!Bindings.ResourceScriptMapping} resourceScriptMapping
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @param {!Array.<!SDK.Script>} scripts
   */
  constructor(resourceScriptMapping, uiSourceCode, scripts) {
    super();
    console.assert(scripts.length);

    this._resourceScriptMapping = resourceScriptMapping;
    this._uiSourceCode = uiSourceCode;

    if (this._uiSourceCode.contentType().isScript())
      this._script = scripts[scripts.length - 1];

    this._uiSourceCode.addEventListener(
        Workspace.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
    this._uiSourceCode.addEventListener(
        Workspace.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
  }

  /**
   * @param {!Array.<!SDK.Script>} scripts
   * @return {boolean}
   */
  _hasScripts(scripts) {
    return this._script && this._script === scripts[0];
  }

  /**
   * @return {boolean}
   */
  _isDiverged() {
    if (this._uiSourceCode.isDirty())
      return true;
    if (!this._script)
      return false;
    if (typeof this._scriptSource === 'undefined')
      return false;
    const workingCopy = this._uiSourceCode.workingCopy();
    if (!workingCopy)
      return false;

    // Match ignoring sourceURL.
    if (!workingCopy.startsWith(this._scriptSource.trimRight()))
      return true;
    const suffix = this._uiSourceCode.workingCopy().substr(this._scriptSource.length);
    return !!suffix.length && !suffix.match(SDK.Script.sourceURLRegex);
  }

  /**
   * @param {!Common.Event} event
   */
  _workingCopyChanged(event) {
    this._update();
  }

  /**
   * @param {!Common.Event} event
   */
  _workingCopyCommitted(event) {
    if (this._uiSourceCode.project().canSetFileContent())
      return;
    if (!this._script)
      return;
    const debuggerModel = this._resourceScriptMapping._debuggerModel;
    const breakpoints = Bindings.breakpointManager.breakpointsForUISourceCode(this._uiSourceCode);
    const source = this._uiSourceCode.workingCopy();
    debuggerModel.setScriptSource(this._script.scriptId, source, scriptSourceWasSet.bind(this));

    /**
     * @param {?string} error
     * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
     * @this {Bindings.ResourceScriptFile}
     */
    async function scriptSourceWasSet(error, exceptionDetails) {
      if (!error && !exceptionDetails)
        this._scriptSource = source;
      this._update();

      if (!error && !exceptionDetails) {
        // Live edit can cause breakpoints to be in the wrong position, or to be lost altogether.
        // If any breakpoints were in the pre-live edit script, they need to be re-added.
        breakpoints.map(breakpoint => breakpoint.refreshInDebugger());
        return;
      }
      if (!exceptionDetails) {
        Common.console.addMessage(Common.UIString('LiveEdit failed: %s', error), Common.Console.MessageLevel.Warning);
        return;
      }
      const messageText = Common.UIString('LiveEdit compile failed: %s', exceptionDetails.text);
      this._uiSourceCode.addLineMessage(
          Workspace.UISourceCode.Message.Level.Error, messageText, exceptionDetails.lineNumber,
          exceptionDetails.columnNumber);
    }
  }

  _update() {
    if (this._isDiverged() && !this._hasDivergedFromVM)
      this._divergeFromVM();
    else if (!this._isDiverged() && this._hasDivergedFromVM)
      this._mergeToVM();
  }

  _divergeFromVM() {
    this._isDivergingFromVM = true;
    this._resourceScriptMapping._debuggerWorkspaceBinding.updateLocations(this._script);
    delete this._isDivergingFromVM;
    this._hasDivergedFromVM = true;
    this.dispatchEventToListeners(Bindings.ResourceScriptFile.Events.DidDivergeFromVM, this._uiSourceCode);
  }

  _mergeToVM() {
    delete this._hasDivergedFromVM;
    this._isMergingToVM = true;
    this._resourceScriptMapping._debuggerWorkspaceBinding.updateLocations(this._script);
    delete this._isMergingToVM;
    this.dispatchEventToListeners(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._uiSourceCode);
  }

  /**
   * @return {boolean}
   */
  hasDivergedFromVM() {
    return this._hasDivergedFromVM;
  }

  /**
   * @return {boolean}
   */
  isDivergingFromVM() {
    return this._isDivergingFromVM;
  }

  /**
   * @return {boolean}
   */
  isMergingToVM() {
    return this._isMergingToVM;
  }

  checkMapping() {
    if (!this._script || typeof this._scriptSource !== 'undefined') {
      this._mappingCheckedForTest();
      return;
    }
    this._script.requestContent().then(callback.bind(this));

    /**
     * @param {?string} source
     * @this {Bindings.ResourceScriptFile}
     */
    function callback(source) {
      this._scriptSource = source;
      this._update();
      this._mappingCheckedForTest();
    }
  }

  _mappingCheckedForTest() {
  }

  dispose() {
    this._uiSourceCode.removeEventListener(
        Workspace.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
    this._uiSourceCode.removeEventListener(
        Workspace.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
  }

  /**
   * @param {string} sourceMapURL
   */
  addSourceMapURL(sourceMapURL) {
    if (!this._script)
      return;
    this._script.debuggerModel.setSourceMapURL(this._script, sourceMapURL);
  }

  /**
   * @return {boolean}
   */
  hasSourceMapURL() {
    return this._script && !!this._script.sourceMapURL;
  }
};

Bindings.ResourceScriptMapping._frameIdSymbol = Symbol('frameid');

/** @enum {symbol} */
Bindings.ResourceScriptFile.Events = {
  DidMergeToVM: Symbol('DidMergeToVM'),
  DidDivergeFromVM: Symbol('DidDivergeFromVM'),
};
