/*
 * Copyright (C) 2011 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 ServiceWorkerManager extends SDK.SDKModel {
  /**
   * @param {!SDK.Target} target
   */
  constructor(target) {
    super(target);
    target.registerServiceWorkerDispatcher(new ServiceWorkerDispatcher(this));
    this._lastAnonymousTargetId = 0;
    this._agent = target.serviceWorkerAgent();
    /** @type {!Map.<string, !ServiceWorkerRegistration>} */
    this._registrations = new Map();
    this.enable();
    this._forceUpdateSetting = Common.settings.createSetting('serviceWorkerUpdateOnReload', false);
    if (this._forceUpdateSetting.get()) {
      this._forceUpdateSettingChanged();
    }
    this._forceUpdateSetting.addChangeListener(this._forceUpdateSettingChanged, this);
    new ServiceWorkerContextNamer(target, this);
  }

  enable() {
    if (this._enabled) {
      return;
    }
    this._enabled = true;
    this._agent.enable();
  }

  disable() {
    if (!this._enabled) {
      return;
    }
    this._enabled = false;
    this._registrations.clear();
    this._agent.disable();
  }

  /**
   * @return {!Map.<string, !ServiceWorkerRegistration>}
   */
  registrations() {
    return this._registrations;
  }

  /**
   * @param {!Array<string>} urls
   * @return {boolean}
   */
  hasRegistrationForURLs(urls) {
    for (const registration of this._registrations.values()) {
      if (urls.filter(url => url && url.startsWith(registration.scopeURL)).length === urls.length) {
        return true;
      }
    }
    return false;
  }

  /**
   * @param {string} versionId
   * @return {?ServiceWorkerVersion}
   */
  findVersion(versionId) {
    for (const registration of this.registrations().values()) {
      const version = registration.versions.get(versionId);
      if (version) {
        return version;
      }
    }
    return null;
  }

  /**
   * @param {string} registrationId
   */
  deleteRegistration(registrationId) {
    const registration = this._registrations.get(registrationId);
    if (!registration) {
      return;
    }
    if (registration._isRedundant()) {
      this._registrations.delete(registrationId);
      this.dispatchEventToListeners(Events.RegistrationDeleted, registration);
      return;
    }
    registration._deleting = true;
    for (const version of registration.versions.values()) {
      this.stopWorker(version.id);
    }
    this._unregister(registration.scopeURL);
  }

  /**
   * @param {string} registrationId
   */
  updateRegistration(registrationId) {
    const registration = this._registrations.get(registrationId);
    if (!registration) {
      return;
    }
    this._agent.updateRegistration(registration.scopeURL);
  }

  /**
   * @param {string} registrationId
   * @param {string} data
   */
  deliverPushMessage(registrationId, data) {
    const registration = this._registrations.get(registrationId);
    if (!registration) {
      return;
    }
    const origin = Common.ParsedURL.extractOrigin(registration.scopeURL);
    this._agent.deliverPushMessage(origin, registrationId, data);
  }

  /**
   * @param {string} registrationId
   * @param {string} tag
   * @param {boolean} lastChance
   */
  dispatchSyncEvent(registrationId, tag, lastChance) {
    const registration = this._registrations.get(registrationId);
    if (!registration) {
      return;
    }
    const origin = Common.ParsedURL.extractOrigin(registration.scopeURL);
    this._agent.dispatchSyncEvent(origin, registrationId, tag, lastChance);
  }

  /**
   * @param {string} registrationId
   * @param {string} tag
   */
  dispatchPeriodicSyncEvent(registrationId, tag) {
    const registration = this._registrations.get(registrationId);
    if (!registration) {
      return;
    }
    const origin = Common.ParsedURL.extractOrigin(registration.scopeURL);
    this._agent.dispatchPeriodicSyncEvent(origin, registrationId, tag);
  }

  /**
   * @param {string} scope
   */
  _unregister(scope) {
    this._agent.unregister(scope);
  }

  /**
   * @param {string} scope
   */
  startWorker(scope) {
    this._agent.startWorker(scope);
  }

  /**
   * @param {string} scope
   */
  skipWaiting(scope) {
    this._agent.skipWaiting(scope);
  }

  /**
   * @param {string} versionId
   */
  stopWorker(versionId) {
    this._agent.stopWorker(versionId);
  }

  /**
   * @param {string} versionId
   */
  inspectWorker(versionId) {
    this._agent.inspectWorker(versionId);
  }

  /**
   * @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerRegistration>} registrations
   */
  _workerRegistrationUpdated(registrations) {
    for (const payload of registrations) {
      let registration = this._registrations.get(payload.registrationId);
      if (!registration) {
        registration = new ServiceWorkerRegistration(payload);
        this._registrations.set(payload.registrationId, registration);
        this.dispatchEventToListeners(Events.RegistrationUpdated, registration);
        continue;
      }
      registration._update(payload);

      if (registration._shouldBeRemoved()) {
        this._registrations.delete(registration.id);
        this.dispatchEventToListeners(Events.RegistrationDeleted, registration);
      } else {
        this.dispatchEventToListeners(Events.RegistrationUpdated, registration);
      }
    }
  }

  /**
   * @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerVersion>} versions
   */
  _workerVersionUpdated(versions) {
    /** @type {!Set.<!ServiceWorkerRegistration>} */
    const registrations = new Set();
    for (const payload of versions) {
      const registration = this._registrations.get(payload.registrationId);
      if (!registration) {
        continue;
      }
      registration._updateVersion(payload);
      registrations.add(registration);
    }
    for (const registration of registrations) {
      if (registration._shouldBeRemoved()) {
        this._registrations.delete(registration.id);
        this.dispatchEventToListeners(Events.RegistrationDeleted, registration);
      } else {
        this.dispatchEventToListeners(Events.RegistrationUpdated, registration);
      }
    }
  }

  /**
   * @param {!Protocol.ServiceWorker.ServiceWorkerErrorMessage} payload
   */
  _workerErrorReported(payload) {
    const registration = this._registrations.get(payload.registrationId);
    if (!registration) {
      return;
    }
    registration.errors.push(payload);
    this.dispatchEventToListeners(Events.RegistrationErrorAdded, {registration: registration, error: payload});
  }

  /**
   * @return {!Common.Setting}
   */
  forceUpdateOnReloadSetting() {
    return this._forceUpdateSetting;
  }

  _forceUpdateSettingChanged() {
    this._agent.setForceUpdateOnPageLoad(this._forceUpdateSetting.get());
  }
}

/** @enum {symbol} */
export const Events = {
  RegistrationUpdated: Symbol('RegistrationUpdated'),
  RegistrationErrorAdded: Symbol('RegistrationErrorAdded'),
  RegistrationDeleted: Symbol('RegistrationDeleted')
};

/**
 * @implements {Protocol.ServiceWorkerDispatcher}
 * @unrestricted
 */
class ServiceWorkerDispatcher {
  /**
   * @param {!ServiceWorkerManager} manager
   */
  constructor(manager) {
    this._manager = manager;
  }

  /**
   * @override
   * @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerRegistration>} registrations
   */
  workerRegistrationUpdated(registrations) {
    this._manager._workerRegistrationUpdated(registrations);
  }

  /**
   * @override
   * @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerVersion>} versions
   */
  workerVersionUpdated(versions) {
    this._manager._workerVersionUpdated(versions);
  }

  /**
   * @override
   * @param {!Protocol.ServiceWorker.ServiceWorkerErrorMessage} errorMessage
   */
  workerErrorReported(errorMessage) {
    this._manager._workerErrorReported(errorMessage);
  }
}

/**
 * @unrestricted
 */
export class ServiceWorkerVersion {
  /**
   * @param {!ServiceWorkerRegistration} registration
   * @param {!Protocol.ServiceWorker.ServiceWorkerVersion} payload
   */
  constructor(registration, payload) {
    this.registration = registration;
    this._update(payload);
  }

  /**
   * @param {!Protocol.ServiceWorker.ServiceWorkerVersion} payload
   */
  _update(payload) {
    this.id = payload.versionId;
    this.scriptURL = payload.scriptURL;
    const parsedURL = new Common.ParsedURL(payload.scriptURL);
    this.securityOrigin = parsedURL.securityOrigin();
    this.runningStatus = payload.runningStatus;
    this.status = payload.status;
    this.scriptLastModified = payload.scriptLastModified;
    this.scriptResponseTime = payload.scriptResponseTime;
    this.controlledClients = [];
    for (let i = 0; i < payload.controlledClients.length; ++i) {
      this.controlledClients.push(payload.controlledClients[i]);
    }
    this.targetId = payload.targetId || null;
  }

  /**
   * @return {boolean}
   */
  isStartable() {
    return !this.registration.isDeleted && this.isActivated() && this.isStopped();
  }

  /**
   * @return {boolean}
   */
  isStoppedAndRedundant() {
    return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopped &&
        this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Redundant;
  }

  /**
   * @return {boolean}
   */
  isStopped() {
    return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopped;
  }

  /**
   * @return {boolean}
   */
  isStarting() {
    return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Starting;
  }

  /**
   * @return {boolean}
   */
  isRunning() {
    return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Running;
  }

  /**
   * @return {boolean}
   */
  isStopping() {
    return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopping;
  }

  /**
   * @return {boolean}
   */
  isNew() {
    return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.New;
  }

  /**
   * @return {boolean}
   */
  isInstalling() {
    return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Installing;
  }

  /**
   * @return {boolean}
   */
  isInstalled() {
    return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Installed;
  }

  /**
   * @return {boolean}
   */
  isActivating() {
    return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Activating;
  }

  /**
   * @return {boolean}
   */
  isActivated() {
    return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Activated;
  }

  /**
   * @return {boolean}
   */
  isRedundant() {
    return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Redundant;
  }

  /**
   * @return {string}
   */
  mode() {
    if (this.isNew() || this.isInstalling()) {
      return ServiceWorkerVersion.Modes.Installing;
    } else if (this.isInstalled()) {
      return ServiceWorkerVersion.Modes.Waiting;
    } else if (this.isActivating() || this.isActivated()) {
      return ServiceWorkerVersion.Modes.Active;
    }
    return ServiceWorkerVersion.Modes.Redundant;
  }
}

/**
 * @type {!Object<string, string>}
 */
ServiceWorkerVersion.RunningStatus = {
  [Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Running]: ls`running`,
  [Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Starting]: ls`starting`,
  [Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopped]: ls`stopped`,
  [Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopping]: ls`stopping`,
};

/**
 * @type {!Object<string, string>}
 */
ServiceWorkerVersion.Status = {
  [Protocol.ServiceWorker.ServiceWorkerVersionStatus.Activated]: ls`activated`,
  [Protocol.ServiceWorker.ServiceWorkerVersionStatus.Activating]: ls`activating`,
  [Protocol.ServiceWorker.ServiceWorkerVersionStatus.Installed]: ls`installed`,
  [Protocol.ServiceWorker.ServiceWorkerVersionStatus.Installing]: ls`installing`,
  [Protocol.ServiceWorker.ServiceWorkerVersionStatus.New]: ls`new`,
  [Protocol.ServiceWorker.ServiceWorkerVersionStatus.Redundant]: ls`redundant`,
};

/**
 * @enum {string}
 */
ServiceWorkerVersion.Modes = {
  Installing: 'installing',
  Waiting: 'waiting',
  Active: 'active',
  Redundant: 'redundant'
};

/**
 * @unrestricted
 */
export class ServiceWorkerRegistration {
  /**
   * @param {!Protocol.ServiceWorker.ServiceWorkerRegistration} payload
   */
  constructor(payload) {
    this._update(payload);
    /** @type {!Map.<string, !ServiceWorkerVersion>} */
    this.versions = new Map();
    this._deleting = false;
    /** @type {!Array<!Protocol.ServiceWorker.ServiceWorkerErrorMessage>} */
    this.errors = [];
  }

  /**
   * @param {!Protocol.ServiceWorker.ServiceWorkerRegistration} payload
   */
  _update(payload) {
    this._fingerprint = Symbol('fingerprint');
    this.id = payload.registrationId;
    this.scopeURL = payload.scopeURL;
    const parsedURL = new Common.ParsedURL(payload.scopeURL);
    this.securityOrigin = parsedURL.securityOrigin();
    this.isDeleted = payload.isDeleted;
    this.forceUpdateOnPageLoad = payload.forceUpdateOnPageLoad;
  }

  /**
   * @return {symbol}
   */
  fingerprint() {
    return this._fingerprint;
  }

  /**
   * @return {!Map<string, !ServiceWorkerVersion>}
   */
  versionsByMode() {
    /** @type {!Map<string, !ServiceWorkerVersion>} */
    const result = new Map();
    for (const version of this.versions.values()) {
      result.set(version.mode(), version);
    }
    return result;
  }

  /**
   * @param {!Protocol.ServiceWorker.ServiceWorkerVersion} payload
   * @return {!ServiceWorkerVersion}
   */
  _updateVersion(payload) {
    this._fingerprint = Symbol('fingerprint');
    let version = this.versions.get(payload.versionId);
    if (!version) {
      version = new ServiceWorkerVersion(this, payload);
      this.versions.set(payload.versionId, version);
      return version;
    }
    version._update(payload);
    return version;
  }

  /**
   * @return {boolean}
   */
  _isRedundant() {
    for (const version of this.versions.values()) {
      if (!version.isStoppedAndRedundant()) {
        return false;
      }
    }
    return true;
  }

  /**
   * @return {boolean}
   */
  _shouldBeRemoved() {
    return this._isRedundant() && (!this.errors.length || this._deleting);
  }

  /**
   * @return {boolean}
   */
  canBeRemoved() {
    return this.isDeleted || this._deleting;
  }


  clearErrors() {
    this._fingerprint = Symbol('fingerprint');
    this.errors = [];
  }
}

/**
 * @unrestricted
 */
class ServiceWorkerContextNamer {
  /**
   * @param {!SDK.Target} target
   * @param {!ServiceWorkerManager} serviceWorkerManager
   */
  constructor(target, serviceWorkerManager) {
    this._target = target;
    this._serviceWorkerManager = serviceWorkerManager;
    /** @type {!Map<string, !ServiceWorkerVersion>} */
    this._versionByTargetId = new Map();
    serviceWorkerManager.addEventListener(Events.RegistrationUpdated, this._registrationsUpdated, this);
    serviceWorkerManager.addEventListener(Events.RegistrationDeleted, this._registrationsUpdated, this);
    SDK.targetManager.addModelListener(
        SDK.RuntimeModel, SDK.RuntimeModel.Events.ExecutionContextCreated, this._executionContextCreated, this);
  }

  /**
   * @param {!Common.Event} event
   */
  _registrationsUpdated(event) {
    this._versionByTargetId.clear();
    const registrations = this._serviceWorkerManager.registrations().valuesArray();
    for (const registration of registrations) {
      const versions = registration.versions.valuesArray();
      for (const version of versions) {
        if (version.targetId) {
          this._versionByTargetId.set(version.targetId, version);
        }
      }
    }
    this._updateAllContextLabels();
  }

  /**
   * @param {!Common.Event} event
   */
  _executionContextCreated(event) {
    const executionContext = /** @type {!SDK.ExecutionContext} */ (event.data);
    const serviceWorkerTargetId = this._serviceWorkerTargetId(executionContext.target());
    if (!serviceWorkerTargetId) {
      return;
    }
    this._updateContextLabel(executionContext, this._versionByTargetId.get(serviceWorkerTargetId) || null);
  }

  /**
   * @param {!SDK.Target} target
   * @return {?string}
   */
  _serviceWorkerTargetId(target) {
    if (target.parentTarget() !== this._target || target.type() !== SDK.Target.Type.ServiceWorker) {
      return null;
    }
    return target.id();
  }

  _updateAllContextLabels() {
    for (const target of SDK.targetManager.targets()) {
      const serviceWorkerTargetId = this._serviceWorkerTargetId(target);
      if (!serviceWorkerTargetId) {
        continue;
      }
      const version = this._versionByTargetId.get(serviceWorkerTargetId) || null;
      const runtimeModel = target.model(SDK.RuntimeModel);
      const executionContexts = runtimeModel ? runtimeModel.executionContexts() : [];
      for (const context of executionContexts) {
        this._updateContextLabel(context, version);
      }
    }
  }

  /**
   * @param {!SDK.ExecutionContext} context
   * @param {?ServiceWorkerVersion} version
   */
  _updateContextLabel(context, version) {
    if (!version) {
      context.setLabel('');
      return;
    }
    const parsedUrl = Common.ParsedURL.fromString(context.origin);
    const label = parsedUrl ? parsedUrl.lastPathComponentWithFragment() : context.name;
    const localizedStatus = ServiceWorkerVersion.Status[version.status];
    context.setLabel(ls`${label} #${version.id} (${localizedStatus})`);
  }
}

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

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

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

/** @enum {symbol} */
SDK.ServiceWorkerManager.Events = Events;

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

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

SDK.SDKModel.register(ServiceWorkerManager, SDK.Target.Capability.ServiceWorker, true);
