// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @unrestricted
 */
export default class PersistenceImpl extends Common.Object {
  /**
   * @param {!Workspace.Workspace} workspace
   * @param {!Bindings.BreakpointManager} breakpointManager
   */
  constructor(workspace, breakpointManager) {
    super();
    this._workspace = workspace;
    this._breakpointManager = breakpointManager;
    /** @type {!Map<string, number>} */
    this._filePathPrefixesToBindingCount = new Map();

    /** @type {!Platform.Multimap<!Workspace.UISourceCode, function()>} */
    this._subscribedBindingEventListeners = new Platform.Multimap();

    const linkDecorator = new Persistence.PersistenceUtils.LinkDecorator(this);
    Components.Linkifier.setLinkDecorator(linkDecorator);

    this._mapping =
        new Persistence.Automapping(this._workspace, this._onStatusAdded.bind(this), this._onStatusRemoved.bind(this));
  }

  /**
   * @param {function(!Workspace.UISourceCode):boolean} interceptor
   */
  addNetworkInterceptor(interceptor) {
    this._mapping.addNetworkInterceptor(interceptor);
  }

  refreshAutomapping() {
    this._mapping.scheduleRemap();
  }

  /**
   * @param {!PersistenceBinding} binding
   */
  addBinding(binding) {
    this._innerAddBinding(binding);
  }

  /**
   * @param {!PersistenceBinding} binding
   */
  addBindingForTest(binding) {
    this._innerAddBinding(binding);
  }

  /**
   * @param {!PersistenceBinding} binding
   */
  removeBinding(binding) {
    this._innerRemoveBinding(binding);
  }

  /**
   * @param {!PersistenceBinding} binding
   */
  removeBindingForTest(binding) {
    this._innerRemoveBinding(binding);
  }

  /**
   * @param {!PersistenceBinding} binding
   */
  _innerAddBinding(binding) {
    binding.network[_binding] = binding;
    binding.fileSystem[_binding] = binding;

    binding.fileSystem.forceLoadOnCheckContent();

    binding.network.addEventListener(
        Workspace.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
    binding.fileSystem.addEventListener(
        Workspace.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
    binding.network.addEventListener(
        Workspace.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this);
    binding.fileSystem.addEventListener(
        Workspace.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this);

    this._addFilePathBindingPrefixes(binding.fileSystem.url());

    this._moveBreakpoints(binding.fileSystem, binding.network);

    console.assert(!binding.fileSystem.isDirty() || !binding.network.isDirty());
    if (binding.fileSystem.isDirty()) {
      this._syncWorkingCopy(binding.fileSystem);
    } else if (binding.network.isDirty()) {
      this._syncWorkingCopy(binding.network);
    } else if (binding.network.hasCommits() && binding.network.content() !== binding.fileSystem.content()) {
      binding.network.setWorkingCopy(binding.network.content());
      this._syncWorkingCopy(binding.network);
    }

    this._notifyBindingEvent(binding.network);
    this._notifyBindingEvent(binding.fileSystem);
    this.dispatchEventToListeners(Events.BindingCreated, binding);
  }

  /**
   * @param {!PersistenceBinding} binding
   */
  _innerRemoveBinding(binding) {
    if (binding.network[_binding] !== binding) {
      return;
    }
    console.assert(
        binding.network[_binding] === binding.fileSystem[_binding],
        'ERROR: inconsistent binding for networkURL ' + binding.network.url());

    binding.network[_binding] = null;
    binding.fileSystem[_binding] = null;

    binding.network.removeEventListener(
        Workspace.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
    binding.fileSystem.removeEventListener(
        Workspace.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
    binding.network.removeEventListener(
        Workspace.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this);
    binding.fileSystem.removeEventListener(
        Workspace.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this);

    this._removeFilePathBindingPrefixes(binding.fileSystem.url());
    this._breakpointManager.copyBreakpoints(binding.network.url(), binding.fileSystem);

    this._notifyBindingEvent(binding.network);
    this._notifyBindingEvent(binding.fileSystem);
    this.dispatchEventToListeners(Events.BindingRemoved, binding);
  }

  /**
   * @param {!Persistence.AutomappingStatus} status
   */
  _onStatusAdded(status) {
    const binding = new PersistenceBinding(status.network, status.fileSystem);
    status[_binding] = binding;
    this._innerAddBinding(binding);
  }

  /**
   * @param {!Persistence.AutomappingStatus} status
   */
  _onStatusRemoved(status) {
    const binding = /** @type {!PersistenceBinding} */ (status[_binding]);
    this._innerRemoveBinding(binding);
  }

  /**
   * @param {!Common.Event} event
   */
  _onWorkingCopyChanged(event) {
    const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
    this._syncWorkingCopy(uiSourceCode);
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   */
  _syncWorkingCopy(uiSourceCode) {
    const binding = uiSourceCode[_binding];
    if (!binding || binding[_muteWorkingCopy]) {
      return;
    }
    const other = binding.network === uiSourceCode ? binding.fileSystem : binding.network;
    if (!uiSourceCode.isDirty()) {
      binding[_muteWorkingCopy] = true;
      other.resetWorkingCopy();
      binding[_muteWorkingCopy] = false;
      this._contentSyncedForTest();
      return;
    }

    const target = Bindings.NetworkProject.targetForUISourceCode(binding.network);
    if (target.type() === SDK.Target.Type.Node) {
      const newContent = uiSourceCode.workingCopy();
      other.requestContent().then(() => {
        const nodeJSContent = PersistenceImpl.rewrapNodeJSContent(other, other.workingCopy(), newContent);
        setWorkingCopy.call(this, () => nodeJSContent);
      });
      return;
    }

    setWorkingCopy.call(this, () => uiSourceCode.workingCopy());

    /**
     * @param {function():string} workingCopyGetter
     * @this {PersistenceImpl}
     */
    function setWorkingCopy(workingCopyGetter) {
      binding[_muteWorkingCopy] = true;
      other.setWorkingCopyGetter(workingCopyGetter);
      binding[_muteWorkingCopy] = false;
      this._contentSyncedForTest();
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _onWorkingCopyCommitted(event) {
    const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data.uiSourceCode);
    const newContent = /** @type {string} */ (event.data.content);
    this.syncContent(uiSourceCode, newContent, event.data.encoded);
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @param {string} newContent
   * @param {boolean} encoded
   */
  syncContent(uiSourceCode, newContent, encoded) {
    const binding = uiSourceCode[_binding];
    if (!binding || binding[_muteCommit]) {
      return;
    }
    const other = binding.network === uiSourceCode ? binding.fileSystem : binding.network;
    const target = Bindings.NetworkProject.targetForUISourceCode(binding.network);
    if (target.type() === SDK.Target.Type.Node) {
      other.requestContent().then(currentContent => {
        const nodeJSContent = PersistenceImpl.rewrapNodeJSContent(other, currentContent.content, newContent);
        setContent.call(this, nodeJSContent);
      });
      return;
    }
    setContent.call(this, newContent);

    /**
     * @param {string} newContent
     * @this {PersistenceImpl}
     */
    function setContent(newContent) {
      binding[_muteCommit] = true;
      other.setContent(newContent, encoded);
      binding[_muteCommit] = false;
      this._contentSyncedForTest();
    }
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @param {string} currentContent
   * @param {string} newContent
   * @return {string}
   */
  static rewrapNodeJSContent(uiSourceCode, currentContent, newContent) {
    if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) {
      if (newContent.startsWith(_NodePrefix) && newContent.endsWith(_NodeSuffix)) {
        newContent = newContent.substring(_NodePrefix.length, newContent.length - _NodeSuffix.length);
      }
      if (currentContent.startsWith(_NodeShebang)) {
        newContent = _NodeShebang + newContent;
      }
    } else {
      if (newContent.startsWith(_NodeShebang)) {
        newContent = newContent.substring(_NodeShebang.length);
      }
      if (currentContent.startsWith(_NodePrefix) && currentContent.endsWith(_NodeSuffix)) {
        newContent = _NodePrefix + newContent + _NodeSuffix;
      }
    }
    return newContent;
  }

  _contentSyncedForTest() {
  }

  /**
   * @param {!Workspace.UISourceCode} from
   * @param {!Workspace.UISourceCode} to
   */
  _moveBreakpoints(from, to) {
    const breakpoints = this._breakpointManager.breakpointLocationsForUISourceCode(from).map(
        breakpointLocation => breakpointLocation.breakpoint);
    for (const breakpoint of breakpoints) {
      breakpoint.remove(false /* keepInStorage */);
      this._breakpointManager.setBreakpoint(
          to, breakpoint.lineNumber(), breakpoint.columnNumber(), breakpoint.condition(), breakpoint.enabled());
    }
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {boolean}
   */
  hasUnsavedCommittedChanges(uiSourceCode) {
    if (this._workspace.hasResourceContentTrackingExtensions()) {
      return false;
    }
    if (uiSourceCode.project().canSetFileContent()) {
      return false;
    }
    if (uiSourceCode[_binding]) {
      return false;
    }
    return !!uiSourceCode.hasCommits();
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {?PersistenceBinding}
   */
  binding(uiSourceCode) {
    return uiSourceCode[_binding] || null;
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @param {function()} listener
   */
  subscribeForBindingEvent(uiSourceCode, listener) {
    this._subscribedBindingEventListeners.set(uiSourceCode, listener);
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @param {function()} listener
   */
  unsubscribeFromBindingEvent(uiSourceCode, listener) {
    this._subscribedBindingEventListeners.delete(uiSourceCode, listener);
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   */
  _notifyBindingEvent(uiSourceCode) {
    if (!this._subscribedBindingEventListeners.has(uiSourceCode)) {
      return;
    }
    const listeners = Array.from(this._subscribedBindingEventListeners.get(uiSourceCode));
    for (const listener of listeners) {
      listener.call(null);
    }
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {?Workspace.UISourceCode}
   */
  fileSystem(uiSourceCode) {
    const binding = this.binding(uiSourceCode);
    return binding ? binding.fileSystem : null;
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {?Workspace.UISourceCode}
   */
  network(uiSourceCode) {
    const binding = this.binding(uiSourceCode);
    return binding ? binding.network : null;
  }

  /**
   * @param {string} filePath
   */
  _addFilePathBindingPrefixes(filePath) {
    let relative = '';
    for (const token of filePath.split('/')) {
      relative += token + '/';
      const count = this._filePathPrefixesToBindingCount.get(relative) || 0;
      this._filePathPrefixesToBindingCount.set(relative, count + 1);
    }
  }

  /**
   * @param {string} filePath
   */
  _removeFilePathBindingPrefixes(filePath) {
    let relative = '';
    for (const token of filePath.split('/')) {
      relative += token + '/';
      const count = this._filePathPrefixesToBindingCount.get(relative);
      if (count === 1) {
        this._filePathPrefixesToBindingCount.delete(relative);
      } else {
        this._filePathPrefixesToBindingCount.set(relative, count - 1);
      }
    }
  }

  /**
   * @param {string} filePath
   * @return {boolean}
   */
  filePathHasBindings(filePath) {
    if (!filePath.endsWith('/')) {
      filePath += '/';
    }
    return this._filePathPrefixesToBindingCount.has(filePath);
  }
}

const _binding = Symbol('Persistence.Binding');
const _muteCommit = Symbol('Persistence.MuteCommit');
const _muteWorkingCopy = Symbol('Persistence.MuteWorkingCopy');
const _NodePrefix = '(function (exports, require, module, __filename, __dirname) { ';
const _NodeSuffix = '\n});';
const _NodeShebang = '#!/usr/bin/env node';

export const Events = {
  BindingCreated: Symbol('BindingCreated'),
  BindingRemoved: Symbol('BindingRemoved')
};

/**
 * @unrestricted
 */
export class PathEncoder {
  constructor() {
    /** @type {!Common.CharacterIdMap<string>} */
    this._encoder = new Common.CharacterIdMap();
  }

  /**
   * @param {string} path
   * @return {string}
   */
  encode(path) {
    return path.split('/').map(token => this._encoder.toChar(token)).join('');
  }

  /**
   * @param {string} path
   * @return {string}
   */
  decode(path) {
    return path.split('').map(token => this._encoder.fromChar(token)).join('/');
  }
}

/**
 * @unrestricted
 */
export class PersistenceBinding {
  /**
   * @param {!Workspace.UISourceCode} network
   * @param {!Workspace.UISourceCode} fileSystem
   */
  constructor(network, fileSystem) {
    this.network = network;
    this.fileSystem = fileSystem;
  }
}

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

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

/** @constructor */
Persistence.Persistence = PersistenceImpl;

Persistence.Persistence.Events = Events;
Persistence.Persistence._NodeShebang = _NodeShebang;
Persistence.Persistence._NodePrefix = _NodePrefix;
Persistence.Persistence._NodeSuffix = _NodeSuffix;

/** @constructor */
Persistence.PathEncoder = PathEncoder;

/** @constructor */
Persistence.PersistenceBinding = PersistenceBinding;

/** @type {!PersistenceImpl} */
Persistence.persistence;
