// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { assert } from 'chrome://resources/js/assert.js';
import { loadTimeData } from 'chrome://resources/js/load_time_data.js';
import { getRequiredElement } from 'chrome://resources/js/util.js';
import { html, render } from 'chrome://resources/lit/v3_0/lit.rollup.js';
import { HIDDEN_CLASS } from './constants.js';
import { Runner } from './dino_game/offline.js';
let showingDetails = false;
let lastData = null;
// Flag to ensure that the Dino game's global singletons (like loadTimeData.data
// and the Runner instance) are only initialized once. This prevents assertion
// errors that occur if these are set/initialized multiple times, which can
// happen in cases such as during testing
let dinoGameInitialized = false;
function toggleHelpBox() {
    showingDetails = !showingDetails;
    assert(lastData);
    render(getHtml(lastData, showingDetails), getRequiredElement('content'));
}
function diagnoseErrors() {
    if (window.errorPageController) {
        window.errorPageController.diagnoseErrorsButtonClick();
    }
}
function portalSignin() {
    if (window.errorPageController) {
        window.errorPageController.portalSigninButtonClick();
    }
}
// Subframes use a different layout but the same html file.  This is to make it
// easier to support platforms that load the error page via different
// mechanisms (Currently just iOS).
let isSubFrame = false;
if (window.top.location !== window.location) {
    document.documentElement.setAttribute('subframe', '');
    isSubFrame = true;
}
// Re-renders the error page using |data| as the dictionary of values.
// Used by NetErrorTabHelper to update DNS error pages with probe results.
function updateForDnsProbe(newData) {
    updateInitialInstruction(newData);
    onTemplateDataReceived(newData);
}
function getMainFrameErrorCssClass(showingDetails) {
    return showingDetails ? 'showing-details' : '';
}
function getMainFrameErrorIconCssClass(data) {
    return isSubFrame ? '' : data.iconClass;
}
function getSubFrameErrorIconCssClass(data) {
    return isSubFrame ? data.iconClass : '';
}
function shouldShowSuggestionsSummaryList(data) {
    return !!data.suggestionsSummaryList &&
        data.suggestionsSummaryList.length > 0;
}
function getSuggestionsSummaryItemCssClass(data) {
    assert(data.suggestionsSummaryList);
    return data.suggestionsSummaryList.length === 1 ? 'single-suggestion' : '';
}
// Implements button clicks.  This function is needed during the transition
// between implementing these in trunk chromium and implementing them in iOS.
function reloadButtonClick(e) {
    const url = e.target.dataset['url'];
    if (window.errorPageController) {
        // 
        // 
        window.errorPageController.reloadButtonClick();
        // 
    }
    else {
        assert(url);
        window.location.href = url;
    }
}
function downloadButtonClick() {
    if (window.errorPageController) {
        window.errorPageController.downloadButtonClick();
        const downloadButton = getRequiredElement('download-button');
        downloadButton.disabled = true;
        downloadButton.textContent = downloadButton.disabledText;
    }
}
function detailsButtonClick() {
    if (window.errorPageController) {
        window.errorPageController.detailsButtonClick();
    }
    toggleHelpBox();
}
function setAutoFetchState(scheduled, canSchedule) {
    getRequiredElement('cancel-save-page-button')
        .classList.toggle(HIDDEN_CLASS, !scheduled);
    getRequiredElement('save-page-for-later-button')
        .classList.toggle(HIDDEN_CLASS, scheduled || !canSchedule);
}
function savePageLaterClick() {
    assert(window.errorPageController);
    window.errorPageController.savePageForLater();
    // savePageForLater will eventually trigger a call to setAutoFetchState() when
    // it completes.
}
function cancelSavePageClick() {
    assert(window.errorPageController);
    window.errorPageController.cancelSavePage();
    // setAutoFetchState is not called in response to cancelSavePage(), so do it
    // now.
    setAutoFetchState(false, true);
}
function shouldShowControlButtons(data) {
    const downloadButtonVisible = !!data.downloadButton && !!data.downloadButton.msg;
    const reloadButtonVisible = !!data.reloadButton && !!data.reloadButton.msg;
    return reloadButtonVisible || downloadButtonVisible;
}
function shouldShowDetailsButton(data) {
    return !!data.suggestionsDetails && data.suggestionsDetails.length > 0;
}
function getDetailsButtonCssClass(data) {
    return shouldShowControlButtons(data) ? '' : 'singular';
}
function getDetailsButtonText(data, showingDetails) {
    assert(data.details);
    assert(data.hideDetails);
    return showingDetails ? data.hideDetails : data.details;
}
// Sets up the proper button layout for the current platform.
function getButtonsCssClass() {
    let primaryControlOnLeft = true;
    // clang-format off
    // 
    // clang-format on
    primaryControlOnLeft = false;
    // 
    return primaryControlOnLeft ? 'suggested-left' : 'suggested-right';
}
// Use device capabilities to guess the most appropriate initial instruction.
function updateInitialInstruction(data) {
    // This method can be called for various error types. Only errors that
    // represent an offline state (as determined by LocalizedError::IsOfflineError
    // in C++, such as net::ERR_INTERNET_DISCONNECTED) result in the dino game
    // being shown. Other errors (e.g., 404, connection reset) do not have the
    // dino game or the localized strings for it, so we skip this logic.
    if (!data.isOfflineError) {
        return;
    }
    if (navigator.maxTouchPoints === 0) {
        // No touch support, so it must be a keyboard/mouse device.
        data.heading.msg = data.dinoGameInstructionsKeyboard;
        data.dinoGameA11yAriaLabel = data.dinoGameA11yAriaLabelKeyboard;
    }
    else if (window.matchMedia('(hover: hover)').matches) {
        // Touch is supported, but so is hovering (e.g. mouse/trackpad).
        // This implies a hybrid device or a tablet with a keyboard/trackpad.
        data.heading.msg = data.dinoGameInstructionsHybrid;
        data.dinoGameA11yAriaLabel = data.dinoGameA11yAriaLabelHybrid;
    }
    else {
        // Touch is supported and hovering is not (e.g. mobile/tablet).
        data.heading.msg = data.dinoGameInstructionsTouch;
        data.dinoGameA11yAriaLabel = data.dinoGameA11yAriaLabelTouch;
    }
}
function onDocumentLoad() {
    const data = window.loadTimeDataRaw;
    updateInitialInstruction(data);
    onTemplateDataReceived(data);
}
function onTemplateDataReceived(newData) {
    lastData = newData;
    render(getHtml(lastData, showingDetails), getRequiredElement('content'));
    if (!isSubFrame && newData.iconClass === 'icon-offline') {
        document.documentElement.classList.add('offline');
        // Set loadTimeData.data because it is used by the dino code.
        if (!dinoGameInitialized) {
            loadTimeData.data = newData;
            Runner.initializeInstance('.interstitial-wrapper');
            dinoGameInitialized = true;
        }
    }
}
function getHtml(data, showingDetails) {
    // clang-format off
    return html `
    <div id="main-frame-error" class="interstitial-wrapper ${getMainFrameErrorCssClass(showingDetails)}">
      <div id="main-content">
        <div class="icon ${getMainFrameErrorIconCssClass(data)}"></div>
        <div id="main-message">
          <h1>
            <span .innerHTML="${data.heading.msg}"></span>
          </h1>
          ${data.summary ? html `
            <p .innerHTML="${data.summary.msg}"></p>
          ` : ''}

          ${shouldShowSuggestionsSummaryList(data) ? html `
            <div id="suggestions-list">
              <p>${data.suggestionsSummaryListHeader}</p>
              <ul class="${getSuggestionsSummaryItemCssClass(data)}">
                ${data.suggestionsSummaryList.map(item => html `
                  <li .innerHTML="${item.summary}"></li>
                `)}
              </ul>
            </div>
          ` : ''}

          <div class="error-code">${data.errorCode}</div>

          ${data.savePageLater ? html `
            <div id="save-page-for-later-button">
              <a class="link-button" @click="${savePageLaterClick}">
                ${data.savePageLater.savePageMsg}
              </a>
            </div>
            <div id="cancel-save-page-button" class="hidden"
                @click="${cancelSavePageClick}"
                .innerHTML="${data.savePageLater.cancelMsg}">
            </div>
          ` : ''}
        </div>
      </div>
      <div id="buttons" class="nav-wrapper ${getButtonsCssClass()}">
        <div id="control-buttons" ?hidden="${!shouldShowControlButtons(data)}">
          ${data.reloadButton ? html `
            <button id="reload-button"
                class="blue-button text-button"
                @click="${reloadButtonClick}"
                data-url="${data.reloadButton.reloadUrl}">
              ${data.reloadButton.msg}
            </button>
          ` : ''}
          ${data.downloadButton ? html `
            <button id="download-button"
                class="blue-button text-button"
                @click="${downloadButtonClick}"
                .disabledText="${data.downloadButton.disabledMsg}">
              ${data.downloadButton.msg}
            </button>
          ` : ''}
        </div>
        ${shouldShowDetailsButton(data) ? html `
          <button id="details-button" class="secondary-button text-button
              small-link ${getDetailsButtonCssClass(data)}"
              @click="${detailsButtonClick}">
            ${getDetailsButtonText(data, showingDetails)}
          </button>
        ` : ''}
      </div>
      ${data.suggestionsDetails ? html `
        <div id="details">
          ${data.suggestionsDetails.map(item => html `
            <div class="suggestions">
              <div class="suggestion-header" .innerHTML="${item.header}"></div>
              <div class="suggestion-body" .innerHTML="${item.body}"></div>
            </div>
          `)}
        </div>
      ` : ''}
    </div>
    ${data.summary ? html `
      <div id="sub-frame-error">
        <!-- Show details when hovering over the icon, in case the details are
             hidden because they're too large. -->
        <div class="icon ${getSubFrameErrorIconCssClass(data)}"></div>
        <div id="sub-frame-error-details" .innerHTML="${data.summary.msg}">
        </div>
      </div>
    ` : ''}
  `;
    // clang-format on
}
// Expose methods that are triggered either
//  - By `onclick=...` handlers in the HTML code, OR
//  - By `href="javascript:..."` in localized links.
//  - By inected JS code coming from C++
//
//  since those need to be available on the 'window' object.
Object.assign(window, {
    diagnoseErrors,
    portalSignin,
    toggleHelpBox,
    updateForDnsProbe,
    updateInitialInstruction,
});
document.addEventListener('DOMContentLoaded', onDocumentLoad);
