/*
 * Copyright (C) 2013 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.
 */

Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
  /**
   * @param {!SourceFrame.SourcesTextEditor} textEditor
   */
  constructor(textEditor) {
    super();
    this._textEditor = textEditor;
    this._swatchPopoverHelper = new InlineEditor.SwatchPopoverHelper();
    this._muteSwatchProcessing = false;
    this._hadSwatchChange = false;
    /** @type {?InlineEditor.BezierEditor} */
    this._bezierEditor = null;
    /** @type {?TextUtils.TextRange} */
    this._editedSwatchTextRange = null;
    /** @type {?ColorPicker.Spectrum} */
    this._spectrum = null;
    /** @type {?Element} */
    this._currentSwatch = null;
    this._textEditor.configureAutocomplete(
        {suggestionsCallback: this._cssSuggestions.bind(this), isWordChar: this._isWordChar.bind(this)});
    this._textEditor.addEventListener(
        SourceFrame.SourcesTextEditor.Events.ScrollChanged, this._textEditorScrolled, this);
    this._textEditor.addEventListener(UI.TextEditor.Events.TextChanged, this._onTextChanged, this);
    this._updateSwatches(0, this._textEditor.linesCount - 1);

    this._shortcuts = {};
    this._registerShortcuts();
    this._boundHandleKeyDown = this._handleKeyDown.bind(this);
    this._textEditor.element.addEventListener('keydown', this._boundHandleKeyDown, false);
  }

  /**
   * @override
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {boolean}
   */
  static accepts(uiSourceCode) {
    return uiSourceCode.contentType().isStyleSheet();
  }

  _registerShortcuts() {
    const shortcutKeys = UI.ShortcutsScreen.SourcesPanelShortcuts;
    for (const descriptor of shortcutKeys.IncreaseCSSUnitByOne) {
      this._shortcuts[descriptor.key] = this._handleUnitModification.bind(this, 1);
    }
    for (const descriptor of shortcutKeys.DecreaseCSSUnitByOne) {
      this._shortcuts[descriptor.key] = this._handleUnitModification.bind(this, -1);
    }
    for (const descriptor of shortcutKeys.IncreaseCSSUnitByTen) {
      this._shortcuts[descriptor.key] = this._handleUnitModification.bind(this, 10);
    }
    for (const descriptor of shortcutKeys.DecreaseCSSUnitByTen) {
      this._shortcuts[descriptor.key] = this._handleUnitModification.bind(this, -10);
    }
  }

  /**
   * @param {!Event} event
   */
  _handleKeyDown(event) {
    const shortcutKey = UI.KeyboardShortcut.makeKeyFromEvent(/** @type {!KeyboardEvent} */ (event));
    const handler = this._shortcuts[shortcutKey];
    if (handler && handler()) {
      event.consume(true);
    }
  }

  _textEditorScrolled() {
    if (this._swatchPopoverHelper.isShowing()) {
      this._swatchPopoverHelper.hide(true);
    }
  }

  /**
   * @param {string} unit
   * @param {number} change
   * @return {?string}
   */
  _modifyUnit(unit, change) {
    const unitValue = parseInt(unit, 10);
    if (isNaN(unitValue)) {
      return null;
    }
    const tail = unit.substring((unitValue).toString().length);
    return String.sprintf('%d%s', unitValue + change, tail);
  }

  /**
   * @param {number} change
   * @return {boolean}
   */
  _handleUnitModification(change) {
    const selection = this._textEditor.selection().normalize();
    let token = this._textEditor.tokenAtTextPosition(selection.startLine, selection.startColumn);
    if (!token) {
      if (selection.startColumn > 0) {
        token = this._textEditor.tokenAtTextPosition(selection.startLine, selection.startColumn - 1);
      }
      if (!token) {
        return false;
      }
    }
    if (token.type !== 'css-number') {
      return false;
    }

    const cssUnitRange =
        new TextUtils.TextRange(selection.startLine, token.startColumn, selection.startLine, token.endColumn);
    const cssUnitText = this._textEditor.text(cssUnitRange);
    const newUnitText = this._modifyUnit(cssUnitText, change);
    if (!newUnitText) {
      return false;
    }
    this._textEditor.editRange(cssUnitRange, newUnitText);
    selection.startColumn = token.startColumn;
    selection.endColumn = selection.startColumn + newUnitText.length;
    this._textEditor.setSelection(selection);
    return true;
  }

  /**
   * @param {number} startLine
   * @param {number} endLine
   */
  _updateSwatches(startLine, endLine) {
    const swatches = [];
    const swatchPositions = [];

    const regexes =
        [SDK.CSSMetadata.VariableRegex, SDK.CSSMetadata.URLRegex, UI.Geometry.CubicBezier.Regex, Common.Color.Regex];
    const handlers = new Map();
    handlers.set(Common.Color.Regex, this._createColorSwatch.bind(this));
    handlers.set(UI.Geometry.CubicBezier.Regex, this._createBezierSwatch.bind(this));

    for (let lineNumber = startLine; lineNumber <= endLine; lineNumber++) {
      const line = this._textEditor.line(lineNumber).substring(0, Sources.CSSPlugin.maxSwatchProcessingLength);
      const results = TextUtils.TextUtils.splitStringByRegexes(line, regexes);
      for (let i = 0; i < results.length; i++) {
        const result = results[i];
        if (result.regexIndex === -1 || !handlers.has(regexes[result.regexIndex])) {
          continue;
        }
        const delimiters = /[\s:;,(){}]/;
        const positionBefore = result.position - 1;
        const positionAfter = result.position + result.value.length;
        if (positionBefore >= 0 && !delimiters.test(line.charAt(positionBefore)) ||
            positionAfter < line.length && !delimiters.test(line.charAt(positionAfter))) {
          continue;
        }
        const swatch = handlers.get(regexes[result.regexIndex])(result.value);
        if (!swatch) {
          continue;
        }
        swatches.push(swatch);
        swatchPositions.push(TextUtils.TextRange.createFromLocation(lineNumber, result.position));
      }
    }
    this._textEditor.operation(putSwatchesInline.bind(this));

    /**
     * @this {Sources.CSSPlugin}
     */
    function putSwatchesInline() {
      const clearRange = new TextUtils.TextRange(startLine, 0, endLine, this._textEditor.line(endLine).length);
      this._textEditor.bookmarks(clearRange, Sources.CSSPlugin.SwatchBookmark).forEach(marker => marker.clear());

      for (let i = 0; i < swatches.length; i++) {
        const swatch = swatches[i];
        const swatchPosition = swatchPositions[i];
        const bookmark = this._textEditor.addBookmark(
            swatchPosition.startLine, swatchPosition.startColumn, swatch, Sources.CSSPlugin.SwatchBookmark);
        swatch[Sources.CSSPlugin.SwatchBookmark] = bookmark;
      }
    }
  }

  /**
   * @param {string} text
   * @return {?InlineEditor.ColorSwatch}
   */
  _createColorSwatch(text) {
    const color = Common.Color.parse(text);
    if (!color) {
      return null;
    }
    const swatch = InlineEditor.ColorSwatch.create();
    swatch.setColor(color);
    swatch.iconElement().title = Common.UIString('Open color picker.');
    swatch.iconElement().addEventListener('click', this._swatchIconClicked.bind(this, swatch), false);
    swatch.hideText(true);
    return swatch;
  }

  /**
   * @param {string} text
   * @return {?InlineEditor.BezierSwatch}
   */
  _createBezierSwatch(text) {
    if (!UI.Geometry.CubicBezier.parse(text)) {
      return null;
    }
    const swatch = InlineEditor.BezierSwatch.create();
    swatch.setBezierText(text);
    swatch.iconElement().title = Common.UIString('Open cubic bezier editor.');
    swatch.iconElement().addEventListener('click', this._swatchIconClicked.bind(this, swatch), false);
    swatch.hideText(true);
    return swatch;
  }

  /**
   * @param {!Element} swatch
   * @param {!Event} event
   */
  _swatchIconClicked(swatch, event) {
    event.consume(true);
    this._hadSwatchChange = false;
    this._muteSwatchProcessing = true;
    const swatchPosition = swatch[Sources.CSSPlugin.SwatchBookmark].position();
    this._textEditor.setSelection(swatchPosition);
    this._editedSwatchTextRange = swatchPosition.clone();
    this._editedSwatchTextRange.endColumn += swatch.textContent.length;
    this._currentSwatch = swatch;

    if (swatch instanceof InlineEditor.ColorSwatch) {
      this._showSpectrum(swatch);
    } else if (swatch instanceof InlineEditor.BezierSwatch) {
      this._showBezierEditor(swatch);
    }
  }

  /**
   * @param {!InlineEditor.ColorSwatch} swatch
   */
  _showSpectrum(swatch) {
    if (!this._spectrum) {
      this._spectrum = new ColorPicker.Spectrum();
      this._spectrum.addEventListener(ColorPicker.Spectrum.Events.SizeChanged, this._spectrumResized, this);
      this._spectrum.addEventListener(ColorPicker.Spectrum.Events.ColorChanged, this._spectrumChanged, this);
    }
    this._spectrum.setColor(swatch.color(), swatch.format());
    this._swatchPopoverHelper.show(this._spectrum, swatch.iconElement(), this._swatchPopoverHidden.bind(this));
  }

  /**
   * @param {!Common.Event} event
   */
  _spectrumResized(event) {
    this._swatchPopoverHelper.reposition();
  }

  /**
   * @param {!Common.Event} event
   */
  _spectrumChanged(event) {
    const colorString = /** @type {string} */ (event.data);
    const color = Common.Color.parse(colorString);
    if (!color) {
      return;
    }
    this._currentSwatch.setColor(color);
    this._changeSwatchText(colorString);
  }

  /**
   * @param {!InlineEditor.BezierSwatch} swatch
   */
  _showBezierEditor(swatch) {
    if (!this._bezierEditor) {
      this._bezierEditor = new InlineEditor.BezierEditor();
      this._bezierEditor.addEventListener(InlineEditor.BezierEditor.Events.BezierChanged, this._bezierChanged, this);
    }
    let cubicBezier = UI.Geometry.CubicBezier.parse(swatch.bezierText());
    if (!cubicBezier) {
      cubicBezier =
          /** @type {!UI.Geometry.CubicBezier} */ (UI.Geometry.CubicBezier.parse('linear'));
    }
    this._bezierEditor.setBezier(cubicBezier);
    this._swatchPopoverHelper.show(this._bezierEditor, swatch.iconElement(), this._swatchPopoverHidden.bind(this));
  }

  /**
   * @param {!Common.Event} event
   */
  _bezierChanged(event) {
    const bezierString = /** @type {string} */ (event.data);
    this._currentSwatch.setBezierText(bezierString);
    this._changeSwatchText(bezierString);
  }

  /**
   * @param {string} text
   */
  _changeSwatchText(text) {
    this._hadSwatchChange = true;
    this._textEditor.editRange(
        /** @type {!TextUtils.TextRange} */ (this._editedSwatchTextRange), text, '*swatch-text-changed');
    this._editedSwatchTextRange.endColumn = this._editedSwatchTextRange.startColumn + text.length;
  }

  /**
   * @param {boolean} commitEdit
   */
  _swatchPopoverHidden(commitEdit) {
    this._muteSwatchProcessing = false;
    if (!commitEdit && this._hadSwatchChange) {
      this._textEditor.undo();
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _onTextChanged(event) {
    if (!this._muteSwatchProcessing) {
      this._updateSwatches(event.data.newRange.startLine, event.data.newRange.endLine);
    }
  }

  /**
   * @param {string} char
   * @return {boolean}
   */
  _isWordChar(char) {
    return TextUtils.TextUtils.isWordChar(char) || char === '.' || char === '-' || char === '$';
  }

  /**
   * @param {!TextUtils.TextRange} prefixRange
   * @param {!TextUtils.TextRange} substituteRange
   * @return {?Promise.<!UI.SuggestBox.Suggestions>}
   */
  _cssSuggestions(prefixRange, substituteRange) {
    const prefix = this._textEditor.text(prefixRange);
    if (prefix.startsWith('$')) {
      return null;
    }

    const propertyToken = this._backtrackPropertyToken(prefixRange.startLine, prefixRange.startColumn - 1);
    if (!propertyToken) {
      return null;
    }

    const line = this._textEditor.line(prefixRange.startLine);
    const tokenContent = line.substring(propertyToken.startColumn, propertyToken.endColumn);
    const propertyValues = SDK.cssMetadata().propertyValues(tokenContent);
    return Promise.resolve(propertyValues.filter(value => value.startsWith(prefix)).map(value => ({text: value})));
  }

  /**
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?{startColumn: number, endColumn: number, type: string}}
   */
  _backtrackPropertyToken(lineNumber, columnNumber) {
    const backtrackDepth = 10;
    let tokenPosition = columnNumber;
    const line = this._textEditor.line(lineNumber);
    let seenColon = false;

    for (let i = 0; i < backtrackDepth && tokenPosition >= 0; ++i) {
      const token = this._textEditor.tokenAtTextPosition(lineNumber, tokenPosition);
      if (!token) {
        return null;
      }
      if (token.type === 'css-property') {
        return seenColon ? token : null;
      }
      if (token.type && !(token.type.indexOf('whitespace') !== -1 || token.type.startsWith('css-comment'))) {
        return null;
      }

      if (!token.type && line.substring(token.startColumn, token.endColumn) === ':') {
        if (!seenColon) {
          seenColon = true;
        } else {
          return null;
        }
      }
      tokenPosition = token.startColumn - 1;
    }
    return null;
  }

  /**
   * @override
   */
  dispose() {
    if (this._swatchPopoverHelper.isShowing()) {
      this._swatchPopoverHelper.hide(true);
    }
    this._textEditor.removeEventListener(
        SourceFrame.SourcesTextEditor.Events.ScrollChanged, this._textEditorScrolled, this);
    this._textEditor.removeEventListener(UI.TextEditor.Events.TextChanged, this._onTextChanged, this);
    this._textEditor.bookmarks(this._textEditor.fullRange(), Sources.CSSPlugin.SwatchBookmark)
        .forEach(marker => marker.clear());
    this._textEditor.element.removeEventListener('keydown', this._boundHandleKeyDown, false);
  }
};

/** @type {number} */
Sources.CSSPlugin.maxSwatchProcessingLength = 300;
/** @type {symbol} */
Sources.CSSPlugin.SwatchBookmark = Symbol('swatch');
