/*!
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/* global $, moment, Airflow, window, localStorage, document, hostName, csrfToken, CustomEvent */

import {
  dateTimeAttrFormat,
  formatTimezone,
  isoDateToTimeEl,
  setDisplayedTimezone,
  TimezoneEvent,
} from './datetime_utils';

window.isoDateToTimeEl = isoDateToTimeEl;

/*
 We pull moment in via a webpack entrypoint rather than import
 so that we don't put it in more than a single .js file.
 This "exports" it to be globally available.
*/
window.moment = Airflow.moment;

function displayTime() {
  const now = moment();
  $('#clock')
    .attr('datetime', now.format(dateTimeAttrFormat))
    .html(`${now.format('HH:mm')} <strong>${formatTimezone(now)}</strong>`);
}

function changeDisplayedTimezone(tz) {
  localStorage.setItem('selected-timezone', tz);

  // dispatch an event that React can listen for
  const event = new CustomEvent(TimezoneEvent, {
    detail: tz,
  });
  document.dispatchEvent(event);

  setDisplayedTimezone(tz);
  displayTime();
  $('body').trigger({
    type: 'airflow.timezone-change',
    timezone: tz,
  });
}

const el = document.createElement('span');

export function escapeHtml(text) {
  el.textContent = text;
  return el.innerHTML;
}

window.escapeHtml = escapeHtml;

export function convertSecsToHumanReadable(seconds) {
  const oriSeconds = seconds;
  const floatingPart = oriSeconds - Math.floor(oriSeconds);

  seconds = Math.floor(seconds);

  const secondsPerHour = 60 * 60;
  const secondsPerMinute = 60;

  const hours = Math.floor(seconds / secondsPerHour);
  seconds -= hours * secondsPerHour;

  const minutes = Math.floor(seconds / secondsPerMinute);
  seconds -= minutes * secondsPerMinute;

  let readableFormat = '';
  if (hours > 0) {
    readableFormat += `${hours}Hours `;
  }
  if (minutes > 0) {
    readableFormat += `${minutes}Min `;
  }
  if (seconds + floatingPart > 0) {
    if (Math.floor(oriSeconds) === oriSeconds) {
      readableFormat += `${seconds}Sec`;
    } else {
      seconds += floatingPart;
      readableFormat += `${seconds.toFixed(3)}Sec`;
    }
  }
  return readableFormat;
}
window.convertSecsToHumanReadable = convertSecsToHumanReadable;

function postAsForm(url, parameters) {
  const form = $('<form></form>');

  form.attr('method', 'POST');
  form.attr('action', url);

  $.each(parameters || {}, (key, value) => {
    const field = $('<input></input>');

    field.attr('type', 'hidden');
    field.attr('name', key);
    field.attr('value', value);

    form.append(field);
  });

  const field = $('<input></input>');

  field.attr('type', 'hidden');
  field.attr('name', 'csrf_token');
  field.attr('value', csrfToken);

  form.append(field);

  // The form needs to be a part of the document in order for us to be able
  // to submit it.
  $(document.body).append(form);
  form.submit();
}

window.postAsForm = postAsForm;

function initializeUITimezone() {
  const local = moment.tz.guess();

  const selectedTz = localStorage.getItem('selected-timezone');
  const manualTz = localStorage.getItem('chosen-timezone');

  function setManualTimezone(tz) {
    localStorage.setItem('chosen-timezone', tz);
    if (tz === local && tz === Airflow.serverTimezone) {
      $('#timezone-manual').hide();
      return;
    }

    $('#timezone-manual a').data('timezone', tz).text(formatTimezone(tz));
    $('#timezone-manual').show();
  }

  if (manualTz) {
    setManualTimezone(manualTz);
  }

  changeDisplayedTimezone(selectedTz || Airflow.defaultUITimezone);

  if (Airflow.serverTimezone !== 'UTC') {
    $('#timezone-server a').html(`${formatTimezone(Airflow.serverTimezone)} <span class="label label-primary">Server</span>`);
    $('#timezone-server').show();
  }

  if (Airflow.serverTimezone !== local) {
    $('#timezone-local a')
      .attr('data-timezone', local)
      .html(`${formatTimezone(local)} <span class="label label-info">Local</span>`);
  } else {
    $('#timezone-local').hide();
  }

  $('a[data-timezone]').click((evt) => {
    changeDisplayedTimezone($(evt.currentTarget).data('timezone'));
  });

  $('#timezone-other').typeahead({
    source: $(moment.tz.names().map((tzName) => {
      const category = tzName.split('/', 1)[0];
      return { category, name: tzName.replace('_', ' '), tzName };
    })),
    showHintOnFocus: 'all',
    showCategoryHeader: true,
    items: 'all',
    afterSelect(data) {
      // Clear it for next time we open the pop-up
      this.$element.val('');

      setManualTimezone(data.tzName);
      changeDisplayedTimezone(data.tzName);

      // We need to delay the close event to not be in the form handler,
      // otherwise bootstrap ignores it, thinking it's caused by interaction on
      // the <form>
      setTimeout(() => {
        document.activeElement.blur();
        // Bug in typeahed, it thinks it's still shown!
        this.shown = false;
        this.focused = false;
      }, 1);
    },
  });
}

$(document).ready(() => {
  initializeUITimezone();

  $('#clock')
    .attr('data-original-title', hostName)
    .attr('data-placement', 'bottom')
    .parent()
    .show();

  displayTime();
  setInterval(displayTime, 1000);

  $.ajaxSetup({
    beforeSend(xhr, settings) {
      if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
        xhr.setRequestHeader('X-CSRFToken', csrfToken);
      }
    },
  });

  $.fn.datetimepicker.defaults.format = 'YYYY-MM-DD HH:mm:ssZ';
  $.fn.datetimepicker.defaults.sideBySide = true;
  $('.datetimepicker').datetimepicker();

  // Fix up filter fields from FAB adds to the page. This event is fired after
  // the FAB registered one which adds the new control
  $('#filter_form a.filter').click(() => {
    $('.datetimepicker').datetimepicker();
  });

  // Global Tooltip selector
  $('.js-tooltip').tooltip();
});
