import { readable, writable } from 'svelte/store';

import { stop_refresh } from './common';
import { my } from './my';

let refresh_interval_settings = null;
let refresh_timeout_settings = null;

function createSettingsStore() {
  const { subscribe, set, update } = writable({});

  function updateFunc(res_settings, cb) {
    const recvTime = (new Date()).getTime();

    if (res_settings.status === 200) {
      res_settings.json().then((settings) => {
        if (settings.start)
          settings.start = new Date(settings.start);
        if (settings.end)
          settings.end = new Date(settings.end);
        if (settings.generation)
          settings.generation = new Date(settings.generation);
        if (settings.nextchangetime)
          settings.nextchangetime = new Date(settings.nextchangetime);
        if (!settings.disablesubmitbutton)
          settings.disablesubmitbutton = null;

        settings.recvTime = recvTime;
        const x_fic_time = res_settings.headers.get("x-fic-time");
        if (x_fic_time) {
          settings.currentTime = Math.floor(x_fic_time * 1000);
        } else {
          settings.currentTime = settings.recvTime;
        }

        update((s) => (Object.assign({}, settings)));

        if (cb) {
          cb(settings);
        }
      });
    }
  }

  async function refreshFunc(cb=null, interval=null) {
    if (refresh_interval_settings)
      clearInterval(refresh_interval_settings);
    if (interval === null) {
      interval = Math.floor(Math.random() * 24000) + 32000;
    }
    if (stop_refresh.state) {
      return;
    }
    refresh_interval_settings = setInterval(refreshFunc, interval);

    if (!cb) {
      // Before we start, update settings more frequently.
      cb = function(stgs) {
        const srv_cur = new Date(Date.now() + (stgs.currentTime - stgs.recvTime));

        if (stgs.start > srv_cur) {
          const startIn = stgs.start - srv_cur;
          if (refresh_timeout_settings)
            clearTimeout(refresh_timeout_settings);

          if (startIn > 15000) {
            refresh_timeout_settings = setTimeout(refreshFunc, Math.floor(Math.random() * 3500) + 10000);
          } else if (startIn > 1500) {
            refresh_timeout_settings = setTimeout(refreshFunc, startIn - 1000 - Math.floor(Math.random() * 500))
          } else {
            // On scheduled start time, refresh my.json file
            refresh_timeout_settings = setTimeout(my.refresh, startIn + Math.floor(Math.random() * 200))
          }
        } else if (stgs.nextchangetime > srv_cur) {
          if (refresh_timeout_settings)
            clearTimeout(refresh_timeout_settings);
          refresh_timeout_settings = setTimeout(() => {
            refreshFunc();
            setTimeout(my.refresh, 4500 + Math.floor(Math.random() * 2000));
          }, stgs.nextchangetime - srv_cur + 500 + Math.floor(Math.random() * 500));
        }
      };
    }

    updateFunc(await fetch('settings.json', {headers: {'Accept': 'application/json'}}), cb);
  };

  return {
    subscribe,

    refresh: refreshFunc,

    update: updateFunc,
  }
}

export const settings = createSettingsStore();

function updateTime(settings) {
  const time = {};

  const srv_cur = new Date(Date.now() + (settings.currentTime - settings.recvTime));

  let remain = 0;
  if (settings.start === undefined || settings.start == 0) {
    return time;
  } else if (settings.start > srv_cur) {
    time.startIn = Math.floor((settings.start - srv_cur) / 1000);
    remain = settings.end - settings.start;
  } else if (settings.end > srv_cur) {
    time.startIn = 0;
    remain = settings.end - srv_cur;
  }

  time.progression = 1 - remain / (settings.end - settings.start);

  remain = remain / 1000;

  if (remain < 0) {
    remain = 0;
    time.end = true;
    time.expired = true;
  } else if (remain < 60) {
    time.end = false;
    time.expired = true;
  } else {
    time.end = false;
    time.expired = false;
  }

  time.remaining = remain;
  time.hours = Math.floor(remain / 3600);
  time.minutes = Math.floor((remain % 3600) / 60);
  time.seconds = Math.floor(remain % 60);

  if (time.hours <= 9) {
    time.hours = "0" + time.hours;
  }
  if (time.minutes <= 9) {
    time.minutes = "0" + time.minutes;
  }
  if (time.seconds <= 9) {
    time.seconds = "0" + time.seconds;
  }

  return time;
}

export const time = readable({}, function start(set) {
  let _settings = {};

  const unsubscribe = settings.subscribe((settings) => {
    _settings = settings;
  });

  const interval = setInterval(() => {
    set(updateTime(_settings));
  }, 1000);

  return function stop() {
    clearInterval(interval);
    unsubscribe();
  }
});
