var _inforTables = {
  instances: {},
  get: id => { return _inforTables.instances[id]; }
}
function initInforTables(options = {}){
  if(typeof __infor_base=== 'undefined'){
    console.log('infor-base.js is not included!');
    return;
  }
  const { id } = options;
  const container = $(`infor-table#${id || 'x'}`);
  if(!container.length){
    console.log(`ID #${id} not found!`);
    return;
  }
  const filters = container.find('infor-table-filters');
  const filters_exist = filters.find('[name]').length !== 0;
  //Count--------------------------------------
  const count_container = container.find('infor-table-count');
  if (!count_container.length){
    console.log('Count container not found!');
    return;
  }
  count_container.html(`
  `)
  //Pagination---------------------------------
  const pagination_container = container.find('infor-table-pagination');
  const order_direction = pagination_container.attr('data-order') || 'DESC';
  if( !pagination_container.length ){
    console.log(`Pagination element not found!`);
    return;
  }
  const { search } = options;
  if(!search){
    console.log('Search parameters are not defined!');
    return;
  }
  pagination_container.addClass('infor-scroll');
  const pagination_order_options = pagination_container.find('infor-table-order-option');
  pagination_container.html(`
    
    
    
    
  
    
  
    
  
    
      
    
  `);
  initInforSearch();
  initInforBarSelector();
  //Table--------------------------------------
  const table_headers = container.find('infor-table-header');
  if(!table_headers.length){
    console.log(`Table headers not found!`);
    return;
  }
  table_headers.remove();
  container.append(`
    
      
        
            
                ${ table_headers.map(function(){
    return `| ${ $(this).text() }`
  }).get().join('') } | 
        
        
      
    
  `);
  //Instance-----------------------------------
  const { fillRecord, api, response_records_name, errorHandler, execute } = options
  if(!fillRecord){
    console.log('FillTable can not be undefined!');
    return;
  }
  if(!api){
    console.log('Api can not be undefined!');
    return;
  }
  const instance = new InforTable({
    id: id,
    container: container,
    api: api,
    response_records_name: response_records_name,
    fillRecord: fillRecord,
    errorHandler: errorHandler,
    execute: execute,
  })
  _inforTables.instances[id] = instance;
  instance.prefillGetValues();
  instance.fetchData();
}
$(document).on('change', 'infor-table [data-order-direction]', function(){
  const checked = $(this).is(':checked');
  const container = findContainerByAttr('data-order-direction-container', this);
  const icon = container.find('i');
  icon.toggleClass('fa-arrow-down-wide-short', !checked);
  icon.toggleClass('fa-arrow-down-short-wide', checked);
})
class InforTable{
  constructor(options) {
    const { id, container, api, response_records_name, fillRecord, errorHandler, execute } = options;
    this.request = null;
    this.id = id;
    this.container = container;
    this.api = api;
    this.search_params = {};
    this.response_records_name = response_records_name;
    this.errorHandler = errorHandler;
    this.execute = execute;
    this.table_container = container.find('infor-table-container')
    this.table = container.find('table');
    this.tbody = container.find('tbody');
    this.refresh_btn = container.find('[data-refresh]');
    this.count_container = container.find('infor-table-count');
    this.records = [];
    this.current_ids = [];
    this.all_ids = [];
    this.fillRecord = fillRecord;
    this.filters = container.find('infor-table-filter')
    this.filters_inputs = this.filters.find('[name]');
    this.page = 1;
    this.pagination = _inforBarSelector.get(`infor_table_${this.id}_pagination`);
    this.pagination.onchange = page => {
      this.page = page;
      this.fetchData();
    };
    this.ids = [];
    this.search = _inforSearch.get(`infor_table_${this.id}_search`);
    this.search.onchange = ids => {
      this.ids = typeof ids == 'object' ? ids : [ids];
      this.pagination.select(1);
    };
    this.order_by_input = this.container.find('[data-order-by]');
    this.order_by = () => { return this.order_by_input.val(); }
    this.order_direction_input = this.container.find('[data-order-direction]');
    this.order_direction = () => { return this.order_direction_input.is(':checked') ? 'ASC' : 'DESC'; }
    this.per_page_input = this.container.find('[data-per-page]');
    this.per_page = () => {
      return this.per_page_input.val();
    }
    this.defineListeners();
  }
  refresh(){
    this.fetchData();
  }
  fetchData(){
    this.setLoader();
    const data = {
      ids: this.ids,
      page: this.page,
      order_by: this.order_by(),
      order_direction: this.order_direction(),
      per_page: this.per_page(),
    }
    this.refreshFilters();
    this.filters_inputs.map((index, element) => {
      const input = $(element);
      const value = input.val();
      const name = input.attr('name');
      if(!value){ return true; }
      //Handle checkbox
      if(name.endsWith('[]')){
        if(!input.is(':checked')){ return true; }
        const refactored_name = name.replace('[]', '');
        if(!data[refactored_name]){ data[refactored_name] = []; }
        data[refactored_name].push(value);
        return true;
      }
      //Handle normal input
      data[name] = value;
    })
    if(this.request){
      this.request.abort();
      this.request = null;
    }
    this.request = _ajax(this.api, data);
    this.request
      .always(() => {
        this.request = null;
      })
      .then(response => {
        this.records = response[this.response_records_name];
        this.all_ids = response.all_ids;
        this.current_ids = response.current_ids;
        this.total_count = this.all_ids.length;
        this.defineSearchParams();
        this.setCount();
        this.fillData();
        this.refreshPagination();
        this.executeFns();
      })
      .catch(this.errorHandler);
  }
  fillData(){
    this.tbody.empty();
    for(const record of this.records){
      this.tbody.append(this.fillRecord(record));
    }
    this.setFilled();
  }
  setCount(){
    const term = Number(this.all_ids.length) === 1 ? this.count_container.attr('data-single') : this.count_container.attr('data-multiple')
    this.count_container.html(` ${this.all_ids.length} ${term} `)
  }
  setLoader(){
    this.count_container.html(``)
  }
  setFilled(){
    this.table_container.attr('data-filled', true);
  }
  refreshFilters(){
    this.filters = this.container.find('infor-table-filter')
    this.filters_inputs = this.filters.find('[name]');
  }
  refreshPagination(){
    const pages_count = Math.ceil((this.total_count || 1) / (this.per_page() || (this.total_count || 1))) // if per_page == '' (no pagination) the pages_count must be 1, also when empty;
    if(pages_count == this.pagination.values().length){
      this.pagination.select(this.page, false);
      return;
    }
    this.pagination.removeAllValues();
    for(let i = 1; i <= pages_count; i++){
      this.pagination.addValue({name: i, value: i});
    }
    this.pagination.select(this.page, false);
  }
  prefillGetValues(){
    this.filters.each((index, element) => {
      const filter = $(element);
      const infor_select_search = filter.find('infor-select-search');
      if(infor_select_search.length){
        const id = infor_select_search.attr('id');
        const value = _get(id);
        if(!value){ return true; }
        _inforSelectSearch.get(id).setValue(value);
        return true;
      }
      const infor_select_multiple = filter.find('infor-select-multiple');
      if(infor_select_multiple.length){
        const id = infor_select_multiple.attr('id');
        const value = _get(id);
        if(!value){ return true; }
        _inforSelectMultiple.get(id).setValues([value]);
        return true;
      }
      const input = filter.find('[name]');
      const name = input.attr('name');
      const value = _get(name);
      if(!value){ return true; }
      input.val(value);
    })
  }
  defineSearchParams(){
    this.search_params = {
      ids: this.all_ids,
    }
  }
  defineListeners(){
    $(this.per_page_input).change(() => {
      _cookieSet(`infor_table_paginate_${this.id}`, this.per_page());
      this.pagination.select(1);
    });
    $(this.filters_inputs).change(() => {
      this.pagination.select(1);
    });
    $(this.order_direction_input).change(() => {
      this.fetchData();
    });
    $(this.order_by_input).change(() => {
      this.fetchData();
    });
    $(this.refresh_btn).click(this.fetchData.bind(this));
  }
  executeFns(){
    if(!Array.isArray(this.execute)){ return; }
    this.execute.map(fn => { fn(); })
  }
}