import 'core-js/stable';
const runtime = require('@wailsapp/runtime');

// TODO: make right clicking on a link copy the url to the clipboard

function fireClick(node){
	if ( document.createEvent ) {
		var evt = document.createEvent('MouseEvents');
		evt.initEvent('click', true, false);
		node.dispatchEvent(evt);    
	} else if( document.createEventObject ) {
		node.fireEvent('onclick') ; 
	} else if (typeof node.onclick == 'function' ) {
		node.onclick(); 
	}
}

function addScheme(url) {
  if (url.indexOf("://") < 3 && url.indexOf(" ") < 0 && url.indexOf(".") > -1) {
    return "gemini://" + url
  }
  return url
}

function handleKeypress(e) {
  if (e.key == 'Escape') {
    let addToListFormModal = document.getElementById('reading-list-form-modal');
    let readingListForm = document.getElementById('add-to-reading-list-form');
    let readingList = document.getElementById('reading-list-display');
    if (addToListFormModal.classList.contains('show')) {
      addToListFormModal.classList.remove('show');
      readingListForm.reset();
    } else if (readingList.classList.contains('open')){
      readingList.classList.remove('open');
    } else {
      backend.AppControl.UnFullscreen()
    }
    return
  }
  if (!e.ctrlKey) {
    return
  }
  let content = document.getElementById('content');
  switch(e.key) {
    case 'q':
      // Quit the application
      e.preventDefault();
      backend.AppControl.Quit();
      break;
    case 'ArrowUp':
    case 'Enter':
      // Fullscreen
      e.preventDefault();
      backend.AppControl.Fullscreen();
      break;
    case 'b':
    case 'ArrowLeft':
      // Go backward
      e.preventDefault();
      fireClick(document.getElementById('ui-back'));
      break;
    case 'f':
    case 'ArrowRight':
      // Go forward
      e.preventDefault();
      fireClick(document.getElementById('ui-forward'));
      break;
    case ' ':
      // Toggle reading list open/closed
      e.preventDefault();
      fireClick(document.getElementById('ui-reading-list-toggle'));
      break;
    case '+':
    case '=':
      // Increase zoom/font-size
      e.preventDefault();
      backend.Settings.IncreaseFontSize().then((size) => {
        content.style.fontSize = size + "px";
      });
      break;
    case '-':
    case '_':
      // Decrease zoom/font-size
      e.preventDefault();
      backend.Settings.DecreaseFontSize().then((size) => {
        let content = document.getElementById('content');
        content.style.fontSize = size + "px";
      });
      break;
    case 'h':
      e.preventDefault();
      fireClick(document.getElementById('ui-home'));
      break;
    case 'r':
      e.preventDefault();
      fireClick(document.getElementById('ui-reload'));
      break;
    case 'a':
      // Select all in main document body
      e.preventDefault();
      window.getSelection().selectAllChildren(content);
      break;
    case 'l':
      // Force a manual load of the config
      e.preventDefault();
      backend.Settings.Load().then(() => console.log('Reloaded configuration file'));
      break;
    case 'S':
      // Force a manual save of the config
      e.preventDefault();
      backend.Settings.Save();
      break;
    case 'u':
      // Focus url bar and select contents
      e.preventDefault();
      let url = document.getElementById('ui-address-input');
      if (url) {
        url.focus();
        url.setSelectionRange(0, url.value.length);
      }
      break;
    case '*':
    case '8':
      // Open 'add to reading list' form dialog
      e.preventDefault();
      var addToListFormModal = document.getElementById('reading-list-form-modal');
      let readingListForm = document.getElementById('add-to-reading-list-form');
      if (addToListFormModal.classList.contains('show')) {
        addToListFormModal.classList.remove('show');
        readingListForm.reset();
      } else {
        let urlInput = document.getElementById('reading-list-input-url');
        let url = document.getElementById('ui-address-input');
        urlInput.value = url.value;
        addToListFormModal.classList.add('show');
        document.getElementById('reading-list-input-title').focus();
      }
  }
}

function parseURL(u, queryString) {
  if (u.indexOf("goldberry://") >= 0) {
    return {string: function() {return u}};
  }
  u = addScheme(u)
  let pattern = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
  let matches =  u.match(pattern);
  let out = {
    scheme: matches[2] ? matches[2] : "",
    authority: matches[4] ? matches[4] : "",
    path: matches[5] ? matches[5] : "/",
    query: matches[7] ? matches[7] : "",
    fragment: matches[9] ? matches[8] : "",
    string: function() {
      let q = "";
      let f = "";
      if (this.query) {
        q = "?" + this.query;
      }
      if (this.fragment) {
        f = "#" + this.fragment;
      }
      return this.scheme + "://" + this.authority + this.path + q + f}
  };

  if (out.scheme && !out.authority) {
    out.authority = out.scheme;
    out.scheme = "gemini";
  }
  if (u.indexOf("://") < 0) {
    out.string = function() {return u};
  }

  if (queryString) {
    out.query = encodeURI(queryString);
  }

  return out;
}

// Main entry point
function start() {
	// Ensure the default app div is 100% wide/high
	var app = document.getElementById('app');
	// app.style.width = '100%';
	// app.style.height = '100%';

	// Inject html
	app.innerHTML = `
  <header id="ui">
    <button id="ui-back" title="Back" aria-label="Go Back">&#x1F448;</button>
    <button id="ui-forward" title="Forward" aria-label="Go Forward">&#x1F449;</button>
    <button id="ui-reload" title="Reload" aria-label="Reload the current document">&#x1F504;</button>
    <button id="ui-home" title="Home" aria-label="Go Home">&#x1F3E1;</button>
    <form id="ui-address-form">
      <input type="text" id="ui-address-input" name="ui-address" value="goldberry://home" />
    </form>
    <button id="ui-reading-list-toggle" title="Toggle Reading List" aria-label="Toggle Reading List Open/Closed">&#128214;</button>
  </header>
  <main id="main" tabindex="0">
    <div id="content"></div>
  </main>
  <div id="ui-url-display"></div>
  <aside id="reading-list-display" aria-modal="true" role="dialog"></aside>
  <aside id="reading-list-form-modal" aria-modal="true" role="dialog" aria-labelledby="rl-modal-header">
    <div id="reading-list-form-header">
      <span id="rl-modal-header">Add To Reading List</span>
      <button id="reading-list-input-cancel" aria-label="Close">&#x274c;</button>
    </div>
    <form id="add-to-reading-list-form">
      <label for="reading-list-input-title">Title</label><br>
      <input type="text" id="reading-list-input-title" name="title" /><br>
      <label for="reading-list-input-url">URL</label><br>
      <input type="text" id="reading-list-input-url" name="url" />
      <input type="submit" id="reading-list-input-submit" value="Add To Reading List" />
    </form>
  </aside>
	`;

  let readingListButton = document.getElementById('ui-reading-list-toggle');
  let readingList = document.getElementById('reading-list-display');
  let readingListFormModal = document.getElementById('reading-list-form-modal');
  let readingListForm = document.getElementById('add-to-reading-list-form');
  let readingListCancel = document.getElementById('reading-list-input-cancel');
  let form = document.getElementById('ui-address-form');
  let url = document.getElementById('ui-address-input');
  let main = document.getElementById('main');
  let content = document.getElementById('content');
  let submitEvent = new Event('submit');
  let backButton = document.getElementById('ui-back');
  let forwardButton = document.getElementById('ui-forward');
  let reloadButton = document.getElementById('ui-reload');
  let homeButton = document.getElementById('ui-home');
  let urlDisplay = document.getElementById('ui-url-display');
  let previousURL = "";

  backend.Settings.FontSize().then((s) => {content.style.fontSize = s + "px";});

  backend.AppControl.GetHomeText().then((h) => {
    content.innerHTML = h;
    addAnchorListeners();
  });

  url.focus({preventScroll: true});
  url.setSelectionRange(0, url.value.length);

  var showUrlTip = (e) => {
    urlDisplay.innerText = event.target.href;
    urlDisplay.classList.add('active');
  }

  var hideUrlTip = (e) => {
    urlDisplay.classList.remove('active');
    urlDisplay.innerText = "";
  }

  var makeRequest = (u, addToHistory) => {
    if (url) {
      let urlObj = parseURL(u)
      if (u.indexOf(' ') > -1 ) {
        urlObj.string = function(){ return u; };
      }
      url.classList.add('loading');
      backend.NavigateTo(urlObj.string()).then((val) => {
        hideUrlTip();
        url.value = urlObj.string();
        content.innerHTML = val;
        addAnchorListeners();
        url.classList.remove('loading');
        if (addToHistory) {
          backend.History.Add(url.value)
          backend.Settings.AddToHistory(url.value)
          previousURL = url.value
        }
        main.focus({preventScroll: true});
        main.scroll({top: 0});
        addSearchFormListeners();
      }, (err) => {
        url.classList.remove('loading');
        url.value = previousURL;
        console.log(err)
      });
    }
  }

  var handleClick = (e) => {
    e.preventDefault()
    if (e.target.href != "") {
      makeRequest(e.target.href, true);
      if (readingList.classList.contains('open')) {
        fireClick(readingListButton);
      }
    }
  };

  var handleRightClick = (e) => {
    e.preventDefault();
    backend.AppControl.WriteToClipboard(e.target.href);
  }

  var anchorListener = (item) => {
    item.addEventListener('click', handleClick);
    item.addEventListener('focusin', showUrlTip);
    item.addEventListener('focusout', hideUrlTip);
    item.addEventListener('mouseover', showUrlTip);
    item.addEventListener('mouseout', hideUrlTip);
    item.addEventListener('contextmenu', handleRightClick);
  }

  var addAnchorListeners = () => {
    document.querySelectorAll('#content a').forEach(anchorListener)
  };

  var addSearchFormListeners = () => {
    document.querySelectorAll('form#search').forEach(form => {
      var input = document.getElementById('QueryResponse');
      form.addEventListener('submit', (e) => {
        e.preventDefault();
        let target = parseURL(form.action, input.value);
        makeRequest(target.string(), true);
      });
      input.focus()
    });
  }

  if (reloadButton) {
    reloadButton.addEventListener('click', (e) => {
      makeRequest(url.value, false);
    });
  }

  if (homeButton) {
    homeButton.addEventListener('click', (e) => {
      makeRequest("goldberry://home", true)
    });
  }

  // Window Event Handlers
  document.addEventListener('keydown', handleKeypress);

  // Form Event Handler(s)
  if (form) {
    form.addEventListener('submit', (e) => {
      e.preventDefault();
      if (url) {
        makeRequest(url.value, true);
      } else {
        console.log("url is undefined");
      }
    });
  }

  let deleteReadingListItem = function(e) {
    let index = this.dataset.index;
    backend.Settings.RemoveFromReadingList(Number(index)).then((html) => {
      document.getElementById('rl-' + index).remove();
      this.remove();
    });
  }

  // Handle reading list opening, closing, and removing items
  if (readingList && readingListButton) {
    readingListButton.addEventListener('click', (e) => {
      if (readingList.classList.contains('open')) {
        // Close it and delete the contents
        readingList.classList.remove('open');
        main.focus();
        setTimeout(() => {readingList.innerHTML = "";}, 300);
      } else {
        // Add contents and open it
        backend.Settings.ReadingListHTML().then((val) => {
          readingList.innerHTML = val;
          document.querySelectorAll('.reading-list-delete').forEach(deleteButton => {
            deleteButton.addEventListener('click', deleteReadingListItem);
          });
          document.querySelectorAll('#reading-list-display a').forEach(anchorListener);
          readingList.classList.add('open');
          let rlHeader = document.querySelector('#rl-header');
          if (rlHeader) {
            rlHeader.focus();
          }
        });
      }
    });
  }

  // Handle adding to reading list
  if (readingListForm) {
    readingListForm.addEventListener('submit', (e) => {
      e.preventDefault();
      let input = document.getElementById('reading-list-input-title');
      backend.Settings.AddToReadingList(input.value, url.value).then((val) => {
        if (readingList.classList.contains('open')) {
          readingList.innerHTML = val;
        }
      });
      readingListForm.reset();
      readingListFormModal.classList.remove('show');
    });
  }

  if (readingListCancel) {
    readingListCancel.addEventListener('click', (e) => {
      readingListFormModal.classList.remove('show');
      readingListForm.reset();
    })
  }


  // Back Button Event Handler(s)
  if (backButton) {
    backButton.addEventListener('click', (e) => {
      backend.History.Back().then((u) => {
        makeRequest(u, false);
      }, (e) => {
        console.log
      })
    });
  }

  // Forward Button Event Handler(s)
  if (forwardButton) {
    forwardButton.addEventListener('click', (e) => {
      backend.History.Forward().then((u) => {
        makeRequest(u, false);
      }, (e) => {
        console.log
      })
    });
  }
};

// We provide our entrypoint as a callback for runtime.Init
runtime.Init(start);
