/*
 * Copyright (C) 2007, 2008 Apple 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:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
 */

import * as Common from '../common/common.js';
import * as Platform from '../platform/platform.js';
import * as TextUtils from '../text_utils/text_utils.js';
import * as UI from '../ui/ui.js';

export class FontView extends UI.View.SimpleView {
  /**
   * @param {string} mimeType
   * @param {!TextUtils.ContentProvider.ContentProvider} contentProvider
   */
  constructor(mimeType, contentProvider) {
    super(Common.UIString.UIString('Font'));
    this.registerRequiredCSS('source_frame/fontView.css', {enableLegacyPatching: true});
    this.element.classList.add('font-view');
    this._url = contentProvider.contentURL();
    UI.ARIAUtils.setAccessibleName(this.element, ls`Preview of font from ${this._url}`);
    this._mimeType = mimeType;
    this._contentProvider = contentProvider;
    this._mimeTypeLabel = new UI.Toolbar.ToolbarText(mimeType);
    /** @type {?HTMLElement} */
    this.fontPreviewElement;
    /** @type {?HTMLElement} */
    this._dummyElement;
    /** @type {?HTMLStyleElement} */
    this.fontStyleElement;
    /** @type {?boolean} */
    this._inResize;
  }

  /**
   * @override
   * @return {!Promise<!Array<!UI.Toolbar.ToolbarItem>>}
   */
  async toolbarItems() {
    return [this._mimeTypeLabel];
  }

  /**
   * @param {string} uniqueFontName
   * @param {!TextUtils.ContentProvider.DeferredContent} deferredContent
   */
  _onFontContentLoaded(uniqueFontName, deferredContent) {
    const {content} = deferredContent;
    const url = content ? TextUtils.ContentProvider.contentAsDataURL(content, this._mimeType, true) : this._url;
    if (!this.fontStyleElement) {
      return;
    }
    this.fontStyleElement.textContent =
        Platform.StringUtilities.sprintf('@font-face { font-family: "%s"; src: url(%s); }', uniqueFontName, url);
    this.updateFontPreviewSize();
  }

  _createContentIfNeeded() {
    if (this.fontPreviewElement) {
      return;
    }

    const uniqueFontName = 'WebInspectorFontPreview' + (++_fontId);

    this.fontStyleElement = /** @type {!HTMLStyleElement} */ (document.createElement('style'));
    this._contentProvider.requestContent().then(deferredContent => {
      this._onFontContentLoaded(uniqueFontName, deferredContent);
    });
    this.element.appendChild(this.fontStyleElement);

    const fontPreview = /** @type {!HTMLDivElement} */ (document.createElement('div'));
    for (let i = 0; i < _fontPreviewLines.length; ++i) {
      if (i > 0) {
        fontPreview.createChild('br');
      }
      UI.UIUtils.createTextChild(fontPreview, _fontPreviewLines[i]);
    }

    this.fontPreviewElement = /** @type {!HTMLDivElement} */ (fontPreview.cloneNode(true));
    if (!this.fontPreviewElement) {
      return;
    }
    UI.ARIAUtils.markAsHidden(this.fontPreviewElement);
    this.fontPreviewElement.style.overflow = 'hidden';
    this.fontPreviewElement.style.setProperty('font-family', uniqueFontName);
    this.fontPreviewElement.style.setProperty('visibility', 'hidden');

    this._dummyElement = fontPreview;
    this._dummyElement.style.visibility = 'hidden';
    this._dummyElement.style.zIndex = '-1';
    this._dummyElement.style.display = 'inline';
    this._dummyElement.style.position = 'absolute';
    this._dummyElement.style.setProperty('font-family', uniqueFontName);
    this._dummyElement.style.setProperty('font-size', _measureFontSize + 'px');

    this.element.appendChild(this.fontPreviewElement);
  }

  /**
   * @override
   */
  wasShown() {
    this._createContentIfNeeded();

    this.updateFontPreviewSize();
  }

  /**
   * @override
   */
  onResize() {
    if (this._inResize) {
      return;
    }

    this._inResize = true;
    try {
      this.updateFontPreviewSize();
    } finally {
      this._inResize = null;
    }
  }

  _measureElement() {
    if (!this._dummyElement) {
      throw new Error('No font preview loaded');
    }
    this.element.appendChild(this._dummyElement);
    const result = {width: this._dummyElement.offsetWidth, height: this._dummyElement.offsetHeight};
    this.element.removeChild(this._dummyElement);

    return result;
  }

  updateFontPreviewSize() {
    if (!this.fontPreviewElement || !this.isShowing()) {
      return;
    }

    this.fontPreviewElement.style.removeProperty('visibility');
    const dimension = this._measureElement();

    const height = dimension.height;
    const width = dimension.width;

    // Subtract some padding. This should match the paddings in the CSS plus room for the scrollbar.
    const containerWidth = this.element.offsetWidth - 50;
    const containerHeight = this.element.offsetHeight - 30;

    if (!height || !width || !containerWidth || !containerHeight) {
      this.fontPreviewElement.style.removeProperty('font-size');
      return;
    }

    const widthRatio = containerWidth / width;
    const heightRatio = containerHeight / height;
    const finalFontSize = Math.floor(_measureFontSize * Math.min(widthRatio, heightRatio)) - 2;

    this.fontPreviewElement.style.setProperty('font-size', finalFontSize + 'px', undefined);
  }
}

let _fontId = 0;

const _fontPreviewLines = ['ABCDEFGHIJKLM', 'NOPQRSTUVWXYZ', 'abcdefghijklm', 'nopqrstuvwxyz', '1234567890'];
const _measureFontSize = 50;
