/*
* UltraDefrag reports sorting engine.
* Copyright (C) 2018-2024 Green Gate Systems, LLC.
*
* ALL RIGHTS RESERVED. YOU MAY NOT DISTRIBUTE OR MODIFY THIS SOFTWARE.
*
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
* AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD
* THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
* SERVICING, REPAIR OR CORRECTION.
*
* IN NO EVENT WILL THE AUTHORS AND COPYRIGHT HOLDERS BE LIABLE TO YOU
* FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
* DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING
* BUT NOT LIMITED TO LOSS OF DATA OR A FAILURE OF THE PROGRAM TO OPERATE
* WITH ANY OTHER PROGRAMS).
*/

const MAX_FILES_PER_PAGE = 300;

let files = fragmented_files;

let total_pages = Math.ceil(files.length / MAX_FILES_PER_PAGE);
let page = 1;

const table = document.querySelector('.fragmented-files-list');
const headings = table.querySelectorAll('thead td');
const body = table.querySelector('tbody');
const pagers = document.querySelectorAll('.pager');

let pagers_added = false;

// sorting order: 0 means descending, 1 means ascending
let fragments_order = 1;
let size_order = 0;
let path_order = 0;
let comment_order = 1;
let status_order = 1;

function add_pager_button(pager,label){
  const text = document.createTextNode(label);
  const button = document.createElement('div');

  if(label == '<<') button.style.display = 'none';
  if(label == '<') button.style.display = 'none';
  if(label == 1) button.className = 'current-page';

  button.appendChild(text);
  pager.appendChild(button);
}

function add_pagers(){
  if(total_pages < 2) return;

  pagers.forEach(pager => {
    add_pager_button(pager,'<<');
    add_pager_button(pager,'<');

    add_pager_button(pager,'1');

    if(total_pages <= 7){
      for(let i = 1; i < total_pages; i++){
        add_pager_button(pager,`${i+1}`);
      }
    } else {
      for(let i = 1; i < 5; i++){
        add_pager_button(pager,`${i+1}`);
      }

      add_pager_button(pager,'...');
      add_pager_button(pager,`${total_pages}`);
    }

    add_pager_button(pager,'>');
    add_pager_button(pager,'>>');
  });

  pagers_added = true;
}

function update_pagers(){
  if(!pagers_added) return;

  pagers.forEach(pager => {
    const buttons = pager.querySelectorAll('div');
    const count = buttons.length;

    if(page > 1){
      buttons[0].style.display = 'block';
      buttons[1].style.display = 'block';
    } else {
      buttons[0].style.display = 'none';
      buttons[1].style.display = 'none';
    }

    const labels = [];
    if(total_pages <= 7){
      for(let i = 0; i < total_pages; i++){
        labels[i] = i + 1;
      }
    } else {
      if(page < 6){
        for(let i = 0; i < 5; i++){
          labels[i] = i + 1;
        }
        labels[5] = '...';
        labels[6] = total_pages;
      } else {
        if(page > total_pages - 7){
          for(let i = 0; i < 7; i++){
            labels[i] = total_pages - 6 + i;
          }
        } else {
          for(let i = 0; i < 5; i++){
            labels[i] = page + i;
          }
          labels[5] = '...';
          labels[6] = total_pages;
        }
      }
    }

    if(labels.length < 2){
      for(let i = 2; i < count - 2; i++){
        const button = buttons[i];
        button.style.display = 'none';
      }
    } else {
      for(let i = 2; i < count - 2; i++){
        const button = buttons[i];
        const label = labels[i - 2];

        if(label === undefined){
          button.style.display = 'none';
        } else {
          button.style.display = 'block';
          button.innerText = label;

          if(label == page){
            button.className = 'current-page';
          } else {
            if(button.classList.contains('current-page')){
              button.classList.remove('current-page');
            }
          }
        }
      }
    }

    if(page < total_pages){
      buttons[count - 2].style.display = 'block';
      buttons[count - 1].style.display = 'block';
    } else {
      buttons[count - 2].style.display = 'none';
      buttons[count - 1].style.display = 'none';
    }
  });
}

function update_table(files){
  let rows = '';
  for(let i = 0; i < files.length; i++){
    const file = files[i];

    rows += '<tr>';
    rows += `<td>${file.fragments}</td>`;
    rows += `<td>${file.hrsize}</td>`;
    rows += `<td>${file.path}</td>`;
    rows += `<td>${file.comment}</td>`;
    rows += `<td>${file.status}</td>`;
    rows += '</tr>';
  }

  body.innerHTML = rows;
}

function sort_files(criteria){
  if(!files.length) return;

  // sort files
  if(criteria === 'fragments'){
    files.sort((a,b) => {
      const result = a.fragments - b.fragments;
      return fragments_order ? result : -result;
    });
    fragments_order = fragments_order ? 0 : 1;
  } else if(criteria === 'size'){
    files.sort((a,b) => {
      const result = a.size - b.size;
      return size_order ? result : -result;
    });
    size_order = size_order ? 0 : 1;
  } else if(criteria === 'path'){
    files.sort((a,b) => {
      const pa = a.path.toLowerCase();
      const pb = b.path.toLowerCase();
      const result = (pa > pb) ? 1 : (pa === pb) ? 0 : -1;
      return path_order ? -result : result;
    });
    path_order = path_order ? 0 : 1;
  } else if(criteria === 'comment'){
    files.sort((a,b) => {
      const ca = a.comment.toLowerCase();
      const cb = b.comment.toLowerCase();
      const result = (ca > cb) ? 1 : (ca === cb) ? 0 : -1;
      return comment_order ? -result : result;
    });
    comment_order = comment_order ? 0 : 1;
  } else if(criteria === 'status'){
    files.sort((a,b) => {
      const sa = a.status.toLowerCase();
      const sb = b.status.toLowerCase();
      const result = (sa > sb) ? 1 : (sa === sb) ? 0 : -1;
      return status_order ? -result : result;
    });
    status_order = status_order ? 0 : 1;
  } else {
    return; // invalid criteria
  }

  // update pagers
  page = 1;
  update_pagers();

  // update the table
  update_table(files.slice(0,MAX_FILES_PER_PAGE));
}

/**
 * Adds a simple click handler to an element and makes
 * sure double clicks won't trigger anything unexpected.
 */
function addClickHandler(element,handler){
  if(!element || !handler) return;

  element.addEventListener('click',handler);

  element.addEventListener('mousedown',(event) => {
    if(event.detail > 1) event.preventDefault();
  });
}

// add pagers
add_pagers();

// populate the fragmented files list
table.style.display = 'table';
update_table(files.slice(0,MAX_FILES_PER_PAGE));

// add click handlers
addClickHandler(headings[0],() => {sort_files('fragments');});
addClickHandler(headings[1],() => {sort_files('size');});
addClickHandler(headings[2],() => {sort_files('path');});
addClickHandler(headings[3],() => {sort_files('comment');});
addClickHandler(headings[4],() => {sort_files('status');});

pagers.forEach(pager => {
  const buttons = pager.querySelectorAll('div');
  buttons.forEach(button => {
    addClickHandler(button, (event) => {
      const label = event.target.innerText;
      switch(label){
        case '<<':
          page = 1;
          break;
        case '<':
          page --;
          break;
        case '...':
          return;
        case '>':
          page ++;
          break;
        case '>>':
          page = total_pages;
          break;
        default:
          page = label;
      }

      // update pagers
      update_pagers();

      // update the table
      const offset = (page - 1) * MAX_FILES_PER_PAGE;
      update_table(files.slice(offset,offset + MAX_FILES_PER_PAGE));
    });
  });
});

/**
 * Search handling code.
 */
const searchInput = document.querySelector('.search input');
let oldQuery = '';

function filter_files(event){
  const query = searchInput.value.toLowerCase();
  if(query != oldQuery){
    // filter the files
    files = fragmented_files.filter(
      file => file.path.toLowerCase().includes(query)
    );

    // update pagers
    total_pages = Math.ceil(files.length / MAX_FILES_PER_PAGE);
    page = 1;
    update_pagers();

    // update the table
    update_table(files.slice(0,MAX_FILES_PER_PAGE));

    // save the search query
    oldQuery = query;
  }
}

searchInput.addEventListener('keyup', event => filter_files(event));
searchInput.addEventListener('search', event => filter_files(event));

/**
 * Scroll to top button handling code.
 */
const pageHeader = document.querySelector('header');
const scrollToTopBtn = document.querySelector('.scroll-to-top');

const io = new IntersectionObserver(entries => {
    entries.forEach(entry => {
        if(entry.intersectionRatio > 0){
            scrollToTopBtn.style.display = 'none';
        } else {
            scrollToTopBtn.style.display = 'flex';
        }
    });
});

io.observe(pageHeader);

addClickHandler(scrollToTopBtn,event => {
    event.preventDefault();
    window.scrollTo(0,0);
});

/**
 * Color themes management code.
 */
function setTheme(theme){
    const themeStyleContainer = document.querySelector('#theme-style');
    const themeSwitch = document.querySelector('#theme-switch');

    switch(theme){
        case 'light':
            themeStyleContainer.innerHTML = `
                :root {
                    --text-color: rgb(17 24 39); /* gray-900 */
                    --border-color: rgb(229 231 235); /* gray-200 */
                    --highlight-color: rgb(243 244 246); /* gray-100 */
                    --bg-color: white;
                }
            `;
            themeSwitch.href = "javascript:setTheme('dark')";
            themeSwitch.title = "Light theme";
            themeSwitch.innerHTML = `
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path fill="currentColor" stroke="currentColor" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"></path><path stroke="currentColor" d="M12 4v1M17.66 6.344l-.828.828M20.005 12.004h-1M17.66 17.664l-.828-.828M12 20.01V19M6.34 17.664l.835-.836M3.995 12.004h1.01M6 6l.835.836"></path></svg>
            `;
            break;
        case 'dark':
            themeStyleContainer.innerHTML = `
                :root {
                    --text-color: rgb(209 213 219); /* gray-300 */
                    --border-color: #494c50;
                    --highlight-color: #222;
                    --bg-color: #292a2d;
                }
            `;
            themeSwitch.href = "javascript:setTheme('system')";
            themeSwitch.title = "Dark theme";
            themeSwitch.innerHTML = `
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="m17.715 15.15.95.316a1 1 0 0 0-1.445-1.185l.495.869ZM9 6.035l.846.534a1 1 0 0 0-1.14-1.49L9 6.035Zm8.221 8.246a5.47 5.47 0 0 1-2.72.718v2a7.47 7.47 0 0 0 3.71-.98l-.99-1.738Zm-2.72.718A5.5 5.5 0 0 1 9 9.5H7a7.5 7.5 0 0 0 7.5 7.5v-2ZM9 9.5c0-1.079.31-2.082.845-2.93L8.153 5.5A7.47 7.47 0 0 0 7 9.5h2Zm-4 3.368C5 10.089 6.815 7.75 9.292 6.99L8.706 5.08C5.397 6.094 3 9.201 3 12.867h2Zm6.042 6.136C7.718 19.003 5 16.268 5 12.867H3c0 4.48 3.588 8.136 8.042 8.136v-2Zm5.725-4.17c-.81 2.433-3.074 4.17-5.725 4.17v2c3.552 0 6.553-2.327 7.622-5.537l-1.897-.632Z"></path><path fill="currentColor" d="M17 3a1 1 0 0 1 1 1 2 2 0 0 0 2 2 1 1 0 1 1 0 2 2 2 0 0 0-2 2 1 1 0 1 1-2 0 2 2 0 0 0-2-2 1 1 0 1 1 0-2 2 2 0 0 0 2-2 1 1 0 0 1 1-1Z"></path></svg>
            `;
            break;
        default:  
            themeStyleContainer.innerHTML = `
                :root {
                    --text-color: rgb(17 24 39); /* gray-900 */
                    --border-color: rgb(229 231 235); /* gray-200 */
                    --highlight-color: rgb(243 244 246); /* gray-100 */
                    --bg-color: white;
                }
                @media (prefers-color-scheme: dark) {
                    :root {
                        --text-color: rgb(209 213 219); /* gray-300 */
                        --border-color: #494c50;
                        --highlight-color: #222;
                        --bg-color: #292a2d;
                    }
                }
            `;
            themeSwitch.href = "javascript:setTheme('light')";
            themeSwitch.title = "System theme";
            themeSwitch.innerHTML = `
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linejoin="round"><path stroke="currentColor" d="M4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6Z"></path><path stroke="currentColor" stroke-linecap="round" d="M14 15c0 3 2 5 2 5H8s2-2 2-5"></path></svg>
            `;
            break;
    }
}
