import $ from "jquery";
import * as JSX from "./jsx";
import { Header } from "./header";
import { Sidebar } from "./sidebar";

const popup_stack = [];
window.onclick = ( e: Event ) => {
  if( !e.target ) return;

  if( popup_stack.length > 0 ) {
    const last = popup_stack[popup_stack.length - 1];
    if( last.el[0] == e.target || last.el.find( e.target ).length != 0 ) return;
    e.preventDefault();
    e.stopPropagation();
    if( last.fn )
      last.fn();

    popup_stack.pop();
    last.el.remove();
  }
}

/**
 * appends an element to the DOM and saves it in the popup stack to be removed.
**/
export function addPopup( element: JQuery ) {
  document.body.appendChild( element[0] );
  setTimeout( () => popup_stack.push( { el: element, fn: null } ) );
}

/**
 * closes the topmost popup
**/
export function closePopup() {
  if( popup_stack.length > 0 ) {
    const last = popup_stack[popup_stack.length - 1];
    if( last.fn )
      last.fn();

    popup_stack.pop();
    setTimeout( () => last.el.remove() );
  }
}

/**
 * sets a callback that will get executed once the current popup is closed
 **/
export function onPopupClosed( fn: Function ) {
  setTimeout( () => {
    if( popup_stack.length > 0 ) {
      popup_stack[popup_stack.length - 1].fn = fn;
    }
  } );
}

/*
 * accepts "folded" prop
**/
export function RolldownListItem( props: any ) {
  const ret = <div class="rolldown">
    <div class="rolldown-collapsed-container">
      <div class="rolldown-icon-container">&gt;</div>
      <div class="rolldown-collapsed">{props.folded}</div>
    </div>
    <div class="rolldown-expanded-container">
      <div class="rolldown-expanded">{props.children}</div>
    </div>
  </div>;

  ret.onclick = () => {
    $( ret ).toggleClass( "active" );
    $( ret ).find( ".rolldown-expanded-container" ).toggleClass( 'active' );
  };

  return ret;
}

export function Spinner( props: any ) {
  let spinner_steps = [
    '/',
    '-',
    '\\',
    '|',
    '/',
    '-',
    '\\',
    '|'
  ];

  const id = props.id || '';

  let el = $( <div class="spinner" id={ id } style={ props.style || '' } /> );
  let i = 0;
  let loop = () => {
    el.text( spinner_steps[i++] );
    if( i > spinner_steps.length )
      i = 0;

    if( el[0].isConnected )
      setTimeout( loop, 100 );
  };

  setTimeout( loop, 100 );
  return el[0];
}

/*
 * accepts title prop
**/
export function RolldownList( props: any ) {
  return <GroupBox title={props.title} style={props.style} innerStyle="margin: 0px; width: 100%">
    <div class="rolldownlist">
      { props.children }
    </div>
  </GroupBox>
}

/*
 * accepts title prop and optional innerStyle
**/
export function GroupBox( props: any ) {
  return <div class="groupbox" id={props.id || ''} style={props.style || ''}>
    <span class="grouptitle">
      {props.title}
    </span>
    <span class="groupbody" style={props.innerStyle || ''}>
      {props.children}
    </span>
  </div>
}

export function Page( props: any ) {
  return <>
    <Header />
    <div id="page-main">
      <Sidebar />
      <div id="page-main-content">
        {props.children}
      </div>
    </div>

    <BackgroundToggle />
  </>
}

export function DropdownItem( props: any ) {
  return <div class="dropdown-inner" style={ props.style || "" } onclick={ props.onclick || null }>
    {props.children}
  </div>
}

/**
 * supports innerStyle for styling the actual dropdown picker
 **/
export function Dropdown( props: any ) {
  const children = props.children;
  let title = props.title;
  let inline = props.inline;
  let onchange = props.onchange;
  let classes = props.class || '';
  let style = props.style || "";
  let id = props.id || '';
  let innerStyle = props.innerStyle || "";

  const showItems = ( e: Event ) => {
    e.preventDefault();
    const target = $( e.target as HTMLElement );

    const newDropdown = $( <div class="dropdown-wrapper" style={ innerStyle }>
      { children.map( ( child: HTMLElement ) => {
        if( !child.onclick ) child.onclick = onchange; return child;
      } ) }
    </div> );
    target.parent().append( newDropdown[0] );
    setTimeout( () => popup_stack.push( { el: newDropdown, fn: null } ) );
  }

  if( inline ) {
    return <button class={ 'dropdown' + ' ' + classes } style={ style } onclick={ showItems } id={ id }>
      { title }
    </button>
  }
  else {
    return <>
      <label>{ title }</label>
        <button class={ 'dropdown' + ' ' + classes } style={ style } onclick={ showItems } id={ id }>
      </button>
    </>
  }
}

export function OkPopup( props: any ) {
  const children = props.children;
  const classes = props.class || '';
  const style = props.style || '';
  const id = props.id || '';

  const onclick = ( e: Event ) => {
    e.preventDefault();
    e.stopPropagation();
    if( props.onclick )
      props.onclick();

    closePopup();
  }

  return <div class={ "popup-msg " + classes } id={ id } style={ style }>
    { children }
    <div style="display: flex; justify-content: center">
      <button onclick={ onclick }>Ok</button>
    </div>
  </div>
}

export function OkCancelPopup( props: any ) {
  const children = props.children;
  const classes = props.class || '';
  const style = props.style || '';
  const id = props.id || '';

  const onclick = ( e: Event ) => {
    e.preventDefault();
    e.stopPropagation();
    if( props.onclick )
      props.onclick();

    closePopup();
  }

  const oncancel = ( e: Event ) => {
    e.preventDefault();
    e.stopPropagation();

    closePopup();
  }

  return <div class={ "popup-msg " + classes } id={ id } style={ style }>
    { children }
    <div style="display: flex; justify-content: center">
      <button onclick={ onclick } style="margin-right: 10px">Ok</button>
      <button onclick={ oncancel }>Cancel</button>
    </div>
  </div>
}

export function BackgroundToggle() {
  const toggleBackground = () => {
    const main = $( "#page-main" );
    if( main.css( "display" ) == "none" ) {
      main.css( "display", "" );
    } else {
      main.css( "display", "none" );
    }
  }

  return <div id="background-toggle" onclick={ toggleBackground }>
    show background
  </div>
}
