/*
 * 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.
 */
/**
 * @implements {UI.Searchable}
 */
export class JSONView extends UI.VBox {
  /**
   * @param {!ParsedJSON} parsedJSON
   */
  constructor(parsedJSON) {
    super();
    this._initialized = false;
    this.registerRequiredCSS('source_frame/jsonView.css');
    this._parsedJSON = parsedJSON;
    this.element.classList.add('json-view');

    /** @type {?UI.SearchableView} */
    this._searchableView;
    /** @type {!ObjectUI.ObjectPropertiesSection} */
    this._treeOutline;
    /** @type {number} */
    this._currentSearchFocusIndex = 0;
    /** @type {!Array.<!UI.TreeElement>} */
    this._currentSearchTreeElements = [];
    /** @type {?RegExp} */
    this._searchRegex = null;
  }

  /**
   * @param {string} content
   * @return {!Promise<?UI.SearchableView>}
   */
  static async createView(content) {
    // We support non-strict JSON parsing by parsing an AST tree which is why we offload it to a worker.
    const parsedJSON = await JSONView._parseJSON(content);
    if (!parsedJSON || typeof parsedJSON.data !== 'object') {
      return null;
    }

    const jsonView = new JSONView(parsedJSON);
    const searchableView = new UI.SearchableView(jsonView);
    searchableView.setPlaceholder(Common.UIString('Find'));
    jsonView._searchableView = searchableView;
    jsonView.show(searchableView.element);
    return searchableView;
  }

  /**
   * @param {?Object} obj
   * @return {!UI.SearchableView}
   */
  static createViewSync(obj) {
    const jsonView = new JSONView(new ParsedJSON(obj, '', ''));
    const searchableView = new UI.SearchableView(jsonView);
    searchableView.setPlaceholder(Common.UIString('Find'));
    jsonView._searchableView = searchableView;
    jsonView.show(searchableView.element);
    jsonView.element.setAttribute('tabIndex', 0);
    return searchableView;
  }

  /**
   * @param {?string} text
   * @return {!Promise<?ParsedJSON>}
   */
  static _parseJSON(text) {
    let returnObj = null;
    if (text) {
      returnObj = JSONView._extractJSON(/** @type {string} */ (text));
    }
    if (!returnObj) {
      return Promise.resolve(/** @type {?ParsedJSON} */ (null));
    }
    return Formatter.formatterWorkerPool().parseJSONRelaxed(returnObj.data).then(handleReturnedJSON);

    /**
     * @param {*} data
     * @return {?ParsedJSON}
     */
    function handleReturnedJSON(data) {
      if (!data) {
        return null;
      }
      returnObj.data = data;
      return returnObj;
    }
  }

  /**
   * @param {string} text
   * @return {?ParsedJSON}
   */
  static _extractJSON(text) {
    // Do not treat HTML as JSON.
    if (text.startsWith('<')) {
      return null;
    }
    let inner = JSONView._findBrackets(text, '{', '}');
    const inner2 = JSONView._findBrackets(text, '[', ']');
    inner = inner2.length > inner.length ? inner2 : inner;

    // Return on blank payloads or on payloads significantly smaller than original text.
    if (inner.length === -1 || text.length - inner.length > 80) {
      return null;
    }

    const prefix = text.substring(0, inner.start);
    const suffix = text.substring(inner.end + 1);
    text = text.substring(inner.start, inner.end + 1);

    // Only process valid JSONP.
    if (suffix.trim().length && !(suffix.trim().startsWith(')') && prefix.trim().endsWith('('))) {
      return null;
    }

    return new ParsedJSON(text, prefix, suffix);
  }

  /**
   * @param {string} text
   * @param {string} open
   * @param {string} close
   * @return {{start: number, end: number, length: number}}
   */
  static _findBrackets(text, open, close) {
    const start = text.indexOf(open);
    const end = text.lastIndexOf(close);
    let length = end - start - 1;
    if (start === -1 || end === -1 || end < start) {
      length = -1;
    }
    return {start: start, end: end, length: length};
  }

  /**
   * @override
   */
  wasShown() {
    this._initialize();
  }

  _initialize() {
    if (this._initialized) {
      return;
    }
    this._initialized = true;

    const obj = SDK.RemoteObject.fromLocalObject(this._parsedJSON.data);
    const title = this._parsedJSON.prefix + obj.description + this._parsedJSON.suffix;
    this._treeOutline = new ObjectUI.ObjectPropertiesSection(
        obj, title, undefined, undefined, undefined, undefined, true /* showOverflow */);
    this._treeOutline.enableContextMenu();
    this._treeOutline.setEditable(false);
    this._treeOutline.expand();
    this.element.appendChild(this._treeOutline.element);
    this._treeOutline.firstChild().select(true /* omitFocus */, false /* selectedByUser */);
  }

  /**
   * @param {number} index
   */
  _jumpToMatch(index) {
    if (!this._searchRegex) {
      return;
    }
    const previousFocusElement = this._currentSearchTreeElements[this._currentSearchFocusIndex];
    if (previousFocusElement) {
      previousFocusElement.setSearchRegex(this._searchRegex);
    }

    const newFocusElement = this._currentSearchTreeElements[index];
    if (newFocusElement) {
      this._updateSearchIndex(index);
      newFocusElement.setSearchRegex(this._searchRegex, UI.highlightedCurrentSearchResultClassName);
      newFocusElement.reveal();
    } else {
      this._updateSearchIndex(0);
    }
  }

  /**
   * @param {number} count
   */
  _updateSearchCount(count) {
    if (!this._searchableView) {
      return;
    }
    this._searchableView.updateSearchMatchesCount(count);
  }

  /**
   * @param {number} index
   */
  _updateSearchIndex(index) {
    this._currentSearchFocusIndex = index;
    if (!this._searchableView) {
      return;
    }
    this._searchableView.updateCurrentMatchIndex(index);
  }

  /**
   * @override
   */
  searchCanceled() {
    this._searchRegex = null;
    this._currentSearchTreeElements = [];

    for (let element = this._treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) {
      if (!(element instanceof ObjectUI.ObjectPropertyTreeElement)) {
        continue;
      }
      element.revertHighlightChanges();
    }
    this._updateSearchCount(0);
    this._updateSearchIndex(0);
  }

  /**
   * @override
   * @param {!UI.SearchableView.SearchConfig} searchConfig
   * @param {boolean} shouldJump
   * @param {boolean=} jumpBackwards
   */
  performSearch(searchConfig, shouldJump, jumpBackwards) {
    let newIndex = this._currentSearchFocusIndex;
    const previousSearchFocusElement = this._currentSearchTreeElements[newIndex];
    this.searchCanceled();
    this._searchRegex = searchConfig.toSearchRegex(true);

    for (let element = this._treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) {
      if (!(element instanceof ObjectUI.ObjectPropertyTreeElement)) {
        continue;
      }
      const hasMatch = element.setSearchRegex(this._searchRegex);
      if (hasMatch) {
        this._currentSearchTreeElements.push(element);
      }
      if (previousSearchFocusElement === element) {
        const currentIndex = this._currentSearchTreeElements.length - 1;
        if (hasMatch || jumpBackwards) {
          newIndex = currentIndex;
        } else {
          newIndex = currentIndex + 1;
        }
      }
    }
    this._updateSearchCount(this._currentSearchTreeElements.length);

    if (!this._currentSearchTreeElements.length) {
      this._updateSearchIndex(0);
      return;
    }
    newIndex = mod(newIndex, this._currentSearchTreeElements.length);

    this._jumpToMatch(newIndex);
  }

  /**
   * @override
   */
  jumpToNextSearchResult() {
    if (!this._currentSearchTreeElements.length) {
      return;
    }
    const newIndex = mod(this._currentSearchFocusIndex + 1, this._currentSearchTreeElements.length);
    this._jumpToMatch(newIndex);
  }

  /**
   * @override
   */
  jumpToPreviousSearchResult() {
    if (!this._currentSearchTreeElements.length) {
      return;
    }
    const newIndex = mod(this._currentSearchFocusIndex - 1, this._currentSearchTreeElements.length);
    this._jumpToMatch(newIndex);
  }

  /**
   * @override
   * @return {boolean}
   */
  supportsCaseSensitiveSearch() {
    return true;
  }

  /**
   * @override
   * @return {boolean}
   */
  supportsRegexSearch() {
    return true;
  }
}


/**
 * @unrestricted
 */
export class ParsedJSON {
  /**
   * @param {*} data
   * @param {string} prefix
   * @param {string} suffix
   */
  constructor(data, prefix, suffix) {
    this.data = data;
    this.prefix = prefix;
    this.suffix = suffix;
  }
}

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

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

/** @constructor */
SourceFrame.JSONView = JSONView;

/** @constructor */
SourceFrame.ParsedJSON = ParsedJSON;
