import Choices from "choices.js";
import { Sidebar } from './js/sidebar';
import './scss/app.scss'
export interface choiceMap {
  [details: string]: Choices;
}

let choiceObjects: choiceMap = {};

document.addEventListener('DOMContentLoaded', function() {
  changeTheme();
  initcolorTheme();
  initSearch();
  initSidebar();
  initToggle();
  replaceStrings();
  initChoices();
  initBoatActions();
  selectBoatChange();
  addRelationMagic(<HTMLElement>document.querySelector('body'));
  reloadPage();
  setCurrentdate(<HTMLInputElement>document.querySelector('#departure'));
});

function changeTheme() {
  let toggleBtn = <HTMLElement>document.querySelector('#theme-toggle-js');

  if(toggleBtn) {
    toggleBtn.addEventListener('click', function() {
      if(toggleBtn.dataset.theme === 'light') {
        setTheme('dark', true);
      } else {
        setTheme('light', true);
      }
    });
  } 
}

/***
* init javascript
* 1) detect native color scheme or use set theme in local storage
* 2) detect view (desktop or responsive) if on mobile device with touch screen
* 3) set base font size to 112.5% -> 18px
*/
function initcolorTheme() {
  colorThemeWatcher();
  let theme = localStorage.getItem('theme');
  if (theme == null || theme === 'auto') {
      if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
          setTheme('dark', false);
      } else {
          setTheme('light', false);
      }
  } else {
      setTheme(theme)
  }
}

/***
* Listener operating system native color configuration
*/
function colorThemeWatcher() {
  try {
      window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
          setTheme(e.matches ? 'dark' : 'light');
      });
  } catch {
      console.warn('color theme watcher not supported');
  }
}

/**
* Define color scheme, colors without losing the base font size configuration
* and add data-theme to html tag
* @param theme
*/
function setTheme(theme: string, setLocalStorage = true) {
  let toggleBtn = document.querySelector('#theme-toggle-js');

  if (setLocalStorage) {
    localStorage.setItem('theme', theme);
  }
  if (toggleBtn) toggleBtn.setAttribute('data-theme', theme);

  if (document.documentElement.classList.contains('dark') && theme === 'light') {
      document.documentElement.classList.remove('dark');
  } else if(theme === 'dark'){
      document.documentElement.classList.add('dark');
  }
}

function setCurrentdate(input: HTMLInputElement) {
  if(input) {
          const now = new Date();
          const formattedDateTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}T${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
        
          input.value = formattedDateTime;
  }
}

interface ChoiceBoatEvent extends Event{
  detail: {
    value: string; 
    label: string,
    customProperties: {
	amount_seats: number,
	owner: number,
	default_destination: string,
    }
  };
}

function selectBoatChange() {
  const boatSelect = <HTMLSelectElement>document.querySelector('#boat_id');

  if(boatSelect) {
    const boatChoice = new Choices(boatSelect, {
      loadingText: 'Wird geladen...',
      noResultsText: 'Keine Ergebnisse gefunden',
      noChoicesText: 'Keine Ergebnisse gefunden',
      itemSelectText: 'Zum Auswählen klicken',
    } as any);

    boatSelect.addEventListener('addItem', function(e) {
	const event = e as ChoiceBoatEvent;
	const amount_seats = event.detail.customProperties.amount_seats;
	setMaxAmountRowers("newrower", amount_seats);

  	const destination = <HTMLSelectElement>document.querySelector('#destination');
	destination.value = event.detail.customProperties.default_destination;

	if (event.detail.customProperties.owner){
		choiceObjects["newrower"].setChoiceByValue(event.detail.customProperties.owner+"");
	}

        const inputElement = document.getElementById("departure") as HTMLInputElement;
        const now = new Date();
        const formattedDateTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}T${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
        
        inputElement.value = formattedDateTime;

	const distinput = <HTMLInputElement>document.querySelector('#distance_in_km');
	distinput.value = ""; 

	const destinput= <HTMLInputElement>document.querySelector('#destination');
	destinput.dispatchEvent(new Event('input')); 
    },false);

    choiceObjects[boatSelect.id] = boatChoice;
    choiceObjects["boat_id"] = boatChoice;
  }
}

function reloadPage() {
  if (!window.location.href.includes("ergo")){
    let pageTitle = document.title;
    let attentionMessage = 'Riemen- und Dollenbruch';

    document.addEventListener('visibilitychange', function() {
        let isPageActive = !document.hidden;

        if(!isPageActive){
            document.title = attentionMessage;
        } else {
            document.title = pageTitle;
            location.reload();
        }
    });
  }
}

function setMaxAmountRowers(name: string, rowers: number) {
  if(choiceObjects[name]) {
    choiceObjects[name].removeActiveItems(-1);
    //let curSelection = choiceObjects[name].getValue(true);
    //let amount_to_delete = (<any>curSelection).length - rowers;

    //if (amount_to_delete > 0){
    //      let to_delete = (<any>curSelection).slice(-amount_to_delete);
    //      for (let del of to_delete) {
    //        choiceObjects[name].removeActiveItemsByValue(del);
    //      }
    //}

    let input = <HTMLElement>document.querySelector('#'+name);
    if(input) {
      choiceObjects[name].config.maxItemCount = rowers;
      if (rowers === 0) {
        choiceObjects[name].disable()
        input.parentElement?.parentElement?.parentElement?.classList.add('hidden');
        input.parentElement?.parentElement?.parentElement?.classList.add('md:block');
        input.parentElement?.parentElement?.parentElement?.classList.add('opacity-50');
      } else{
        choiceObjects[name].enable();
        input.parentElement?.parentElement?.parentElement?.classList.remove('hidden');
        input.parentElement?.parentElement?.parentElement?.classList.remove('md:block');
        input.parentElement?.parentElement?.parentElement?.classList.remove('opacity-50');
      }
    }

    //let only_steering =  <HTMLSelectElement>document.querySelector('#shipmaster_only_steering');
    //if(only_steering) {
    //  if(isShipmasterSteering == 'true') {
    //    only_steering.removeAttribute('disabled');
    //    only_steering.setAttribute('checked', 'true');
    //    only_steering.parentElement?.parentElement?.parentElement?.classList.remove('hidden');
    //    only_steering.parentElement?.parentElement?.parentElement?.classList.remove('md:block');
    //    only_steering.parentElement?.parentElement?.parentElement?.classList.remove('opacity-50');
    //  } else {
    //    only_steering.setAttribute('disabled', 'disabled');
    //    only_steering.removeAttribute('checked');
    //    only_steering.parentElement?.parentElement?.parentElement?.classList.add('hidden');
    //    only_steering.parentElement?.parentElement?.parentElement?.classList.add('md:block');
    //    only_steering.parentElement?.parentElement?.parentElement?.classList.add('opacity-50');     
    //  }
    //}
    let shipmaster = <HTMLElement>document.querySelector('#shipmaster-'+name+'js');
    let steering_person = <HTMLElement>document.querySelector('#steering_person-'+name+'js');
    if (rowers == 1){
	if (shipmaster.parentNode) {
		(<HTMLElement>shipmaster.parentNode).classList.add('hidden');
	}
	shipmaster.removeAttribute('required');

	if (steering_person.parentNode){
		(<HTMLElement>steering_person.parentNode).classList.add('hidden');
	}
	steering_person.removeAttribute('required');
    }else{
	if (shipmaster.parentNode){
		(<HTMLElement>shipmaster.parentNode).classList.remove('hidden');
	}
	shipmaster.setAttribute('required', 'required');

	if (steering_person.parentNode){
		(<HTMLElement>steering_person.parentNode).classList.remove('hidden');
	}
	steering_person.setAttribute('required', 'required');
    }
  }
}

function initBoatActions() {
  const boatSelects = document.querySelectorAll('.boats-js[data-onclick="true"]');
  if(boatSelects) {
    Array.prototype.forEach.call(boatSelects, (select: HTMLInputElement) => {
      select.addEventListener('click', function() {
        if(select.dataset.seats) {
          if (select.dataset.id) {
                  choiceObjects['boat_id'].setChoiceByValue(select.dataset.id);
          }

          window.scrollTo(0, 0);
        }
      });
    });
  }
}

function initChoices() {
  const selects = document.querySelectorAll('select[data-init="true"]');
  if(selects) {
    Array.prototype.forEach.call(selects, (select: HTMLInputElement) => {
      initNewChoice(select);
    });
  }
}

interface ChoiceEvent extends Event{
  detail: {
    value: string; 
    label: string,
    customProperties: {
	is_cox: boolean,
	steers: boolean,
	cox_on_boat: boolean,
    }
  };
}

function initNewChoice(select: HTMLInputElement) {
  let seats = 0;
  if (select.dataset && select.dataset.seats) {
    seats = +select.dataset.seats;
  }

    let shipmaster = <HTMLElement>document.querySelector('#shipmaster-'+select.id+'js');
    let steering_person = <HTMLElement>document.querySelector('#steering_person-'+select.id+'js');
    if (seats == 1){
	if (shipmaster.parentNode) {
		(<HTMLElement>shipmaster.parentNode).classList.add('hidden');
	}
	shipmaster.removeAttribute('required');

	if (steering_person.parentNode){
		(<HTMLElement>steering_person.parentNode).classList.add('hidden');
	}
	steering_person.removeAttribute('required');
    }else{
	if (shipmaster.parentNode){
		(<HTMLElement>shipmaster.parentNode).classList.remove('hidden');
	}
	shipmaster.setAttribute('required', 'required');

	if (steering_person.parentNode){
		(<HTMLElement>steering_person.parentNode).classList.remove('hidden');
	}
	steering_person.setAttribute('required', 'required');
    }
  const choice = new Choices(select, {
    removeItemButton: true,
    loadingText: 'Wird geladen...',
    noResultsText: 'Keine Ergebnisse gefunden',
    noChoicesText: 'Keine Ergebnisse gefunden',
    itemSelectText: 'Zum Auswählen klicken',
    placeholderValue: 'Ruderer auswählen',
    maxItemCount: seats, 
    maxItemText: (maxItemCount) => {
      return `Nur ${maxItemCount} Ruderer können hinzugefügt werden`;
    },
      callbackOnInit: function() {
              this._currentState.items.forEach(function(obj){
        	if (obj.customProperties && obj.customProperties.is_cox){
        		const coxSelect = <HTMLSelectElement>document.querySelector('#shipmaster-' + select.id + 'js');
        		var new_option = new Option(obj.label, obj.value);
			if (obj.customProperties.cox_on_boat){
				new_option.selected = true;
			}
        		coxSelect.add(new_option);   
        	}
        	const steeringSelect = <HTMLSelectElement>document.querySelector('#steering_person-' + select.id + 'js');
        	if (steeringSelect) {
        		var new_option = new Option(obj.label, obj.value);
			if (obj.customProperties && obj.customProperties.steers){
				new_option.selected = true;
			}
        		steeringSelect.add(new_option);   
        	}
              });
      }
  });
  choiceObjects[select.id] = choice;

    select.addEventListener('addItem', function(e) {
	const event = e as ChoiceEvent;
	const user_id = event.detail.value;
	const name = event.detail.label;

	if (event.detail.customProperties.is_cox) {
		const coxSelect = <HTMLSelectElement>document.querySelector('#shipmaster-' + select.id + 'js');
		if (coxSelect){
			coxSelect.add(new Option(name, user_id));
		}
	}

	const steeringSelect = <HTMLSelectElement>document.querySelector('#steering_person-' + select.id + 'js');
	if (steeringSelect) {
		steeringSelect.add(new Option(name, user_id));   
	}
    },false);

	select.addEventListener('removeItem', function(e) {
		const event = e as ChoiceEvent;

		const user_id = event.detail.value;

		const coxSelect = <HTMLSelectElement>document.querySelector('#shipmaster-' + select.id + 'js');
		if (coxSelect) {
			for (var i=0; i<coxSelect.length; i++) {
	    			if (coxSelect.options[i].value == user_id)
	        			coxSelect.remove(i);
			}
		}

		const steeringSelect = <HTMLSelectElement>document.querySelector('#steering_person-' + select.id + 'js');
		if (steeringSelect) {
			for (var i=0; i<steeringSelect.length; i++) {
	    			if (steeringSelect.options[i].value == user_id)
	        			steeringSelect.remove(i);
			}
		}
	},false);

  choiceObjects[select.id] = choice;
}


function initToggle() {
  // get filter btns & set object sessionStorage
  const btns = <NodeListOf<HTMLButtonElement>>document.querySelectorAll('.filter-trips-js');
  let filterObject = new Map();

  if(btns) {
    Array.prototype.forEach.call(btns, (btn: HTMLButtonElement) => {
      filterObject.set(btn.dataset.action, btn.ariaPressed);
     
      btn.addEventListener('click', () => {
        let filter = sessionStorage.getItem('tripsFilter');
        if(filter) {
          let filterMap = new Map(JSON.parse(filter));
          for (let entry of filterMap.entries()) {
            if(entry[0] === btn.dataset.action && entry[1] !== 'true') {
              filterMap.set(entry[0],'true');
            } else {
              filterMap.set(entry[0],'false');
            }
          }
          sessionStorage.setItem('tripsFilter', JSON.stringify( Array.from(filterMap.entries())));
        }
        resetFilteredElements();
        if(btn.getAttribute('aria-pressed') === 'false'){
          Array.prototype.forEach.call(btns, (b: HTMLButtonElement) => {
            b.setAttribute('aria-pressed', 'false'); 
          });
          triggerFilterAction(btn.dataset.action);
        } else {
          btn.setAttribute('aria-pressed', 'false'); 
        }
      });
    }); 
  }

  let filter = sessionStorage.getItem('tripsFilter');
  if(filter) {
    let filterMap = new Map(JSON.parse(filter));
    for (let entry of filterMap.entries()) {
      if(entry[1] === 'true') {
        triggerFilterAction(entry[0]);
      }
    }
  } else {
    sessionStorage.setItem('tripsFilter', JSON.stringify( Array.from(filterObject.entries())));
  }
}

function resetFilteredElements() {
  const hiddenElements = document.querySelectorAll('.reset-js.hidden');
  if(hiddenElements) {
    Array.prototype.forEach.call(hiddenElements, (hiddenElement: HTMLButtonElement) => {
      hiddenElement.classList.remove('hidden');
    });
  }
}

function triggerFilterAction(activeFilter: any) {
  const activeBtn = document.querySelector('button[data-action="' + activeFilter + '"]');
  if(activeBtn) {
    activeBtn.setAttribute('aria-pressed', 'true'); 

    filterAction(activeFilter);
  } 
}

function filterAction(activeFilter: string) {
  switch(activeFilter) {
    case 'filter-days': {
      filterDays();
      break;
    }
    case 'filter-coxs': {
      filterCoxs();
      break;
    }
    case 'filter-months': {
      filterMonths(activeFilter)
      break;
    }
  }
}

function filterDays() {
  const daysNoTrips = document.querySelectorAll('div[data-trips="0"]');
  Array.prototype.forEach.call(daysNoTrips, (day: HTMLElement) => {
    day.classList.toggle('hidden');
  });
}

function filterCoxs() {
  const noCoxNeeded = document.querySelectorAll('div[data-coxneeded="false"]');
  Array.prototype.forEach.call(noCoxNeeded, (notNeeded: HTMLElement) => {
    notNeeded.classList.toggle('hidden');
  });
}

function filterMonths(action: string) {
  const months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
  const monthToggle = <HTMLButtonElement>document.querySelector('button[data-action="' + action + '"]');
  if(monthToggle) {
      const currentMonth = monthToggle.dataset.month;
      
      if(currentMonth) {
        const index = months.indexOf(currentMonth);
        if (index > -1) { // only splice array when item is found
          months.splice(index, 1); // 2nd parameter means remove one item only
        }

        Array.prototype.forEach.call(months, (month: HTMLElement) => {
          const notThisMonth = document.querySelectorAll('div[data-month="' + month + '"]');
          Array.prototype.forEach.call(notThisMonth, (notThisMonth: HTMLElement) => {
            notThisMonth.classList.toggle('hidden');
          });
        });
      }
    }
  }

function initSearch() {
  const input = <HTMLInputElement>document.querySelector('#filter-js');

  if(input) {
    filterElements(input.value);

    input.addEventListener('input', () => {
      filterElements(input.value);
    });
  }
}

function filterElements(input: string) {
  const elements = document.querySelectorAll('div[data-filterable="true"]');
  let resultWrapper = <HTMLElement>document.querySelector('#filter-result-js'),
      amountShownElements = 0;

  Array.prototype.forEach.call(elements, (element: HTMLElement) => {
    // set both strings (input & dataset filter) to lowercase to not be case sensitive
    let filterString = element.dataset.filter?.toLocaleLowerCase();
    
    // bulk hide all elements
    element.style.display = 'none';

    // show if input matches
    if(filterString?.includes(input.toLocaleLowerCase())) {
      element.style.display = 'flex';
      amountShownElements ++;
    }
  });

  if(resultWrapper) {
    resultWrapper.innerHTML = (amountShownElements === 0 ? 'Kein Ergebnis gefunden' : '<strong>' + amountShownElements + '</strong>' + (amountShownElements > 1 ? ' Ergebnisse' : ' Ergebnis') + ' gefunden');
  }
}

function initSidebar() {
  const sidebarTrigger = <NodeListOf<HTMLElement>>document.querySelectorAll('[data-trigger]');

  if(sidebarTrigger) {
    Array.prototype.forEach.call(sidebarTrigger, (triggerElement: HTMLElement) => {
      if(triggerElement.dataset.trigger) {
        const sidebar = new Sidebar(triggerElement.dataset.trigger);

        triggerElement.addEventListener('click', (e) => {
          e.preventDefault();
          if(triggerElement.dataset.trigger === 'sidebar') {
            initTripSidebar(triggerElement);
          }  

          sidebar.toggle();
        });
      }
    });
  }
}

function initTripSidebar(triggerElement: HTMLElement) {
  const sidebarElement = <HTMLElement>document.querySelector('#sidebar');
  if(sidebarElement && triggerElement.dataset.body && triggerElement.dataset.header) {
    let body = <HTMLElement>document.querySelector(triggerElement.dataset.body);
    let bodyElement = <HTMLElement>body.cloneNode(true);
    let bodyContainerElement = <HTMLElement>sidebarElement.querySelector('.body-js');

    
    /* Quickfix duplicate ids checkboxes */
    const checkboxes = <NodeListOf<HTMLElement>>bodyElement.querySelectorAll('input[type="checkbox"]');

    Array.prototype.forEach.call(checkboxes, (checkbox: HTMLElement) => {
      if(checkbox) {
        checkbox.parentElement?.setAttribute('for', checkbox.id + 'js');
        checkbox.id += 'js';
      }
    });

    const prefixedContent =  <NodeListOf<HTMLElement>>bodyElement.querySelectorAll('.change-id-js');
    Array.prototype.forEach.call(prefixedContent, (content: HTMLElement) => {
      if(content) {
        content.id += 'js';

        if(content.dataset.relation){
          content.dataset.relation += 'js';
        }
      }
    });


    if(bodyContainerElement) {
      bodyContainerElement.innerHTML = '';
      bodyContainerElement.append(bodyElement);

      addRelationMagic(bodyElement);
    }
    if(triggerElement.dataset.day) {
      let hiddenElement = <HTMLInputElement>bodyElement.querySelector('.day-js');
      if(hiddenElement) {
        hiddenElement.value = triggerElement.dataset.day;
      }
    }

    let headerElement = sidebarElement.querySelector('.header-js');
    if(headerElement) {
      headerElement.innerHTML = triggerElement.dataset.header;
    }
    const selects = bodyElement.querySelectorAll('select[multiple]');
     if(selects) {
       Array.prototype.forEach.call(selects, (select: HTMLInputElement) => {
        initNewChoice(select);
       });
     }
  }
    const defaultDateTimes = <NodeListOf<HTMLInputElement>>document.querySelectorAll('.current-date-time');
    defaultDateTimes.forEach((defaultDateTime) => {
	    setCurrentdate(defaultDateTime);
    });

}

function addRelationMagic(bodyElement: HTMLElement) {
  const fields = bodyElement.querySelectorAll('.set-distance-js');

  if(fields) {
    Array.prototype.forEach.call(fields, (field: HTMLInputElement) => {
      if(field.dataset.relation){
        const relatedField = <HTMLInputElement>bodyElement.querySelector('#' + field.dataset.relation);
        if(relatedField) {
          field.addEventListener('input', (e) => {
            e.preventDefault();              
            const dataList = <HTMLDataListElement>document.querySelector('#destinations');
              if(dataList) {
                var option = Array.prototype.find.call(dataList.options, function(option) {
                  return option.value === field.value;
                });
    
                // Get distance
                const distance = option.getAttribute('distance');
                if(distance) relatedField.value = distance;
              }
          });
        }
      }
    });
  }
}

function replaceStrings() {
  const weekdays = document.querySelectorAll('.weekday-js');
  Array.prototype.forEach.call(weekdays, (weekday: HTMLElement) => {
    weekday.innerHTML = weekday.innerHTML.replace('Freitag', 'Markttag');
  });
}