/*
 * 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.
 */

/**
 * @unrestricted
 */
export default class IsolatedFileSystemManager extends Common.Object {
  constructor() {
    super();

    /** @type {!Map<string, !Persistence.PlatformFileSystem>} */
    this._fileSystems = new Map();
    /** @type {!Map<number, function(!Array.<string>)>} */
    this._callbacks = new Map();
    /** @type {!Map<number, !Common.Progress>} */
    this._progresses = new Map();

    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, this._onFileSystemRemoved, this);
    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.FileSystemAdded, this._onFileSystemAdded, this);
    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, this._onFileSystemFilesChanged, this);
    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, this._onIndexingTotalWorkCalculated, this);
    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.IndexingWorked, this._onIndexingWorked, this);
    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.IndexingDone, this._onIndexingDone, this);
    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.SearchCompleted, this._onSearchCompleted, this);

    this._initExcludePatterSetting();

    /** @type {?function(?Persistence.IsolatedFileSystem)} */
    this._fileSystemRequestResolve = null;
    this._fileSystemsLoadedPromise = this._requestFileSystems();
  }

  /**
   * @return {!Promise<!Array<!Persistence.IsolatedFileSystem>>}
   */
  _requestFileSystems() {
    let fulfill;
    const promise = new Promise(f => fulfill = f);
    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.FileSystemsLoaded, onFileSystemsLoaded, this);
    Host.InspectorFrontendHost.requestFileSystems();
    return promise;

    /**
     * @param {!Common.Event} event
     * @this {IsolatedFileSystemManager}
     */
    function onFileSystemsLoaded(event) {
      const fileSystems = /** @type {!Array.<!Persistence.IsolatedFileSystemManager.FileSystem>} */ (event.data);
      const promises = [];
      for (let i = 0; i < fileSystems.length; ++i) {
        promises.push(this._innerAddFileSystem(fileSystems[i], false));
      }
      Promise.all(promises).then(onFileSystemsAdded);
    }

    /**
     * @param {!Array<?Persistence.IsolatedFileSystem>} fileSystems
     */
    function onFileSystemsAdded(fileSystems) {
      fulfill(fileSystems.filter(fs => !!fs));
    }
  }

  /**
   * @param {string=} type
   * @return {!Promise<?Persistence.IsolatedFileSystem>}
   */
  addFileSystem(type) {
    return new Promise(resolve => {
      this._fileSystemRequestResolve = resolve;
      Host.InspectorFrontendHost.addFileSystem(type || '');
    });
  }

  /**
   * @param {!Persistence.PlatformFileSystem} fileSystem
   */
  removeFileSystem(fileSystem) {
    Host.InspectorFrontendHost.removeFileSystem(fileSystem.embedderPath());
  }

  /**
   * @return {!Promise<!Array<!Persistence.IsolatedFileSystem>>}
   */
  waitForFileSystems() {
    return this._fileSystemsLoadedPromise;
  }

  /**
   * @param {!Persistence.IsolatedFileSystemManager.FileSystem} fileSystem
   * @param {boolean} dispatchEvent
   * @return {!Promise<?Persistence.IsolatedFileSystem>}
   */
  _innerAddFileSystem(fileSystem, dispatchEvent) {
    const embedderPath = fileSystem.fileSystemPath;
    const fileSystemURL = Common.ParsedURL.platformPathToURL(fileSystem.fileSystemPath);
    const promise = Persistence.IsolatedFileSystem.create(
        this, fileSystemURL, embedderPath, fileSystem.type, fileSystem.fileSystemName, fileSystem.rootURL);
    return promise.then(storeFileSystem.bind(this));

    /**
     * @param {?Persistence.PlatformFileSystem} fileSystem
     * @this {IsolatedFileSystemManager}
     */
    function storeFileSystem(fileSystem) {
      if (!fileSystem) {
        return null;
      }
      this._fileSystems.set(fileSystemURL, fileSystem);
      if (dispatchEvent) {
        this.dispatchEventToListeners(Events.FileSystemAdded, fileSystem);
      }
      return fileSystem;
    }
  }

  /**
   * @param {string} fileSystemURL
   * @param {!Persistence.PlatformFileSystem} fileSystem
   */
  addPlatformFileSystem(fileSystemURL, fileSystem) {
    this._fileSystems.set(fileSystemURL, fileSystem);
    this.dispatchEventToListeners(Events.FileSystemAdded, fileSystem);
  }

  /**
   * @param {!Common.Event} event
   */
  async _onFileSystemAdded(event) {
    const errorMessage = /** @type {string} */ (event.data['errorMessage']);
    let fileSystem = /** @type {?Persistence.IsolatedFileSystemManager.FileSystem} */ (event.data['fileSystem']);
    if (errorMessage) {
      Common.console.error(Common.UIString('Unable to add filesystem: %s', errorMessage));
      if (!this._fileSystemRequestResolve) {
        return;
      }
      this._fileSystemRequestResolve.call(null, null);
      this._fileSystemRequestResolve = null;
    } else if (fileSystem) {
      fileSystem = await this._innerAddFileSystem(fileSystem, true);
      if (this._fileSystemRequestResolve) {
        this._fileSystemRequestResolve.call(null, fileSystem);
        this._fileSystemRequestResolve = null;
      }
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _onFileSystemRemoved(event) {
    const embedderPath = /** @type {string} */ (event.data);
    const fileSystemPath = Common.ParsedURL.platformPathToURL(embedderPath);
    const isolatedFileSystem = this._fileSystems.get(fileSystemPath);
    if (!isolatedFileSystem) {
      return;
    }
    this._fileSystems.delete(fileSystemPath);
    isolatedFileSystem.fileSystemRemoved();
    this.dispatchEventToListeners(Events.FileSystemRemoved, isolatedFileSystem);
  }

  /**
   * @param {!Common.Event} event
   */
  _onFileSystemFilesChanged(event) {
    const urlPaths = {
      changed: groupFilePathsIntoFileSystemPaths.call(this, event.data.changed),
      added: groupFilePathsIntoFileSystemPaths.call(this, event.data.added),
      removed: groupFilePathsIntoFileSystemPaths.call(this, event.data.removed)
    };

    this.dispatchEventToListeners(Events.FileSystemFilesChanged, urlPaths);

    /**
     * @param {!Array<string>} embedderPaths
     * @return {!Platform.Multimap<string, string>}
     * @this {IsolatedFileSystemManager}
     */
    function groupFilePathsIntoFileSystemPaths(embedderPaths) {
      const paths = new Platform.Multimap();
      for (const embedderPath of embedderPaths) {
        const filePath = Common.ParsedURL.platformPathToURL(embedderPath);
        for (const fileSystemPath of this._fileSystems.keys()) {
          if (this._fileSystems.get(fileSystemPath).isFileExcluded(embedderPath)) {
            continue;
          }
          const pathPrefix = fileSystemPath.endsWith('/') ? fileSystemPath : fileSystemPath + '/';
          if (!filePath.startsWith(pathPrefix)) {
            continue;
          }
          paths.set(fileSystemPath, filePath);
        }
      }
      return paths;
    }
  }

  /**
   * @return {!Array<!Persistence.IsolatedFileSystem>}
   */
  fileSystems() {
    return this._fileSystems.valuesArray();
  }

  /**
   * @param {string} fileSystemPath
   * @return {?Persistence.PlatformFileSystem}
   */
  fileSystem(fileSystemPath) {
    return this._fileSystems.get(fileSystemPath) || null;
  }

  _initExcludePatterSetting() {
    const defaultCommonExcludedFolders = [
      '/node_modules/', '/bower_components/', '/\\.devtools', '/\\.git/', '/\\.sass-cache/', '/\\.hg/', '/\\.idea/',
      '/\\.svn/', '/\\.cache/', '/\\.project/'
    ];
    const defaultWinExcludedFolders = ['/Thumbs.db$', '/ehthumbs.db$', '/Desktop.ini$', '/\\$RECYCLE.BIN/'];
    const defaultMacExcludedFolders = [
      '/\\.DS_Store$', '/\\.Trashes$', '/\\.Spotlight-V100$', '/\\.AppleDouble$', '/\\.LSOverride$', '/Icon$',
      '/\\._.*$'
    ];
    const defaultLinuxExcludedFolders = ['/.*~$'];
    let defaultExcludedFolders = defaultCommonExcludedFolders;
    if (Host.isWin()) {
      defaultExcludedFolders = defaultExcludedFolders.concat(defaultWinExcludedFolders);
    } else if (Host.isMac()) {
      defaultExcludedFolders = defaultExcludedFolders.concat(defaultMacExcludedFolders);
    } else {
      defaultExcludedFolders = defaultExcludedFolders.concat(defaultLinuxExcludedFolders);
    }
    const defaultExcludedFoldersPattern = defaultExcludedFolders.join('|');
    this._workspaceFolderExcludePatternSetting = Common.settings.createRegExpSetting(
        'workspaceFolderExcludePattern', defaultExcludedFoldersPattern, Host.isWin() ? 'i' : '');
  }

  /**
   * @return {!Common.Setting}
   */
  workspaceFolderExcludePatternSetting() {
    return this._workspaceFolderExcludePatternSetting;
  }

  /**
   * @param {function(!Array.<string>)} callback
   * @return {number}
   */
  registerCallback(callback) {
    const requestId = ++_lastRequestId;
    this._callbacks.set(requestId, callback);
    return requestId;
  }

  /**
   * @param {!Common.Progress} progress
   * @return {number}
   */
  registerProgress(progress) {
    const requestId = ++_lastRequestId;
    this._progresses.set(requestId, progress);
    return requestId;
  }

  /**
   * @param {!Common.Event} event
   */
  _onIndexingTotalWorkCalculated(event) {
    const requestId = /** @type {number} */ (event.data['requestId']);
    const totalWork = /** @type {number} */ (event.data['totalWork']);

    const progress = this._progresses.get(requestId);
    if (!progress) {
      return;
    }
    progress.setTotalWork(totalWork);
  }

  /**
   * @param {!Common.Event} event
   */
  _onIndexingWorked(event) {
    const requestId = /** @type {number} */ (event.data['requestId']);
    const worked = /** @type {number} */ (event.data['worked']);

    const progress = this._progresses.get(requestId);
    if (!progress) {
      return;
    }
    progress.worked(worked);
    if (progress.isCanceled()) {
      Host.InspectorFrontendHost.stopIndexing(requestId);
      this._onIndexingDone(event);
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _onIndexingDone(event) {
    const requestId = /** @type {number} */ (event.data['requestId']);

    const progress = this._progresses.get(requestId);
    if (!progress) {
      return;
    }
    progress.done();
    this._progresses.delete(requestId);
  }

  /**
   * @param {!Common.Event} event
   */
  _onSearchCompleted(event) {
    const requestId = /** @type {number} */ (event.data['requestId']);
    const files = /** @type {!Array.<string>} */ (event.data['files']);

    const callback = this._callbacks.get(requestId);
    if (!callback) {
      return;
    }
    callback.call(null, files);
    this._callbacks.delete(requestId);
  }
}

/** @enum {symbol} */
export const Events = {
  FileSystemAdded: Symbol('FileSystemAdded'),
  FileSystemRemoved: Symbol('FileSystemRemoved'),
  FileSystemFilesChanged: Symbol('FileSystemFilesChanged'),
  ExcludedFolderAdded: Symbol('ExcludedFolderAdded'),
  ExcludedFolderRemoved: Symbol('ExcludedFolderRemoved')
};

let _lastRequestId = 0;

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

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

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

/** @enum {symbol} */
Persistence.IsolatedFileSystemManager.Events = Events;

/** @typedef {!{type: string, fileSystemName: string, rootURL: string, fileSystemPath: string}} */
Persistence.IsolatedFileSystemManager.FileSystem;

/** @typedef {!{changed:!Platform.Multimap<string, string>, added:!Platform.Multimap<string, string>, removed:!Platform.Multimap<string, string>}} */
Persistence.IsolatedFileSystemManager.FilesChangedData;

/**
 * @type {!IsolatedFileSystemManager}
 */
Persistence.isolatedFileSystemManager;
