import { Component, h, Fragment, createRef } from 'preact';
import { RpcClient } from 'webextension-rpc';
import type { backgroundRpcServer } from '../background';
import { AnnotationSource } from '../storage/AnnotationSource';
import classes from './AnnotationSourcesList.module.scss';
import cls from 'classnames';
import niceTime from '../util/niceTime';
import { Annotation } from '../storage/Annotation';
import { AnnotationsList } from './AnnotationsList';
import infoIcon from '../assets/icons/info.svg';
import rssIcon from '../assets/icons/rss.svg';

const backgroundRpc = new RpcClient<typeof backgroundRpcServer>();

// Run refresh in the background: should continue if the page/popup is closed.
const refreshAnnotationSource = backgroundRpc.func('refreshAnnotationSource');
const refreshAnnotationSources = backgroundRpc.func('refreshAnnotationSources');

interface AnnotationSourcesListProps {
  withAnnotations?: boolean;
}

interface AnnotationSourcesListState {
  sources?: AnnotationSource[];
  totalAnnotationCount?: number;
}

export class AnnotationSourcesList extends Component<
  AnnotationSourcesListProps,
  AnnotationSourcesListState
> {
  state: AnnotationSourcesListState = {};

  refreshButton = createRef<HTMLButtonElement>();

  async componentDidMount() {
    await this.loadData();
  }

  async loadData() {
    this.setState({
      sources: await AnnotationSource.getAll(),
      // sources: await AnnotationSource.getActiveSources(),
      totalAnnotationCount: await Annotation.count(),
    });
  }

  refreshAll = async () => {
    const button = this.refreshButton.current!;
    try {
      button.classList.add(classes.loading);
      button.disabled = true;
      await refreshAnnotationSources({ forceAll: true });
      await this.loadData();
    } catch (error) {
      alert(`Refreshing failed: ${error}`);
      throw error;
    } finally {
      button.disabled = false;
      button.classList.remove(classes.loading);
    }
  };

  refreshSource = async (source: AnnotationSource) => {
    try {
      await refreshAnnotationSource(source.data, true);
    } catch (error) {
      alert(`Refreshing failed: ${error}`);
    }
    await this.loadData();
  };

  removeSource = async (source: AnnotationSource) => {
    await source.delete();
    await this.loadData();
  };

  render(
    { withAnnotations }: AnnotationSourcesListProps,
    { sources }: AnnotationSourcesListState,
  ) {
    const sourceList = sources?.map((source) => (
      <li
        key={source.data._id}
        class={cls(classes.source, { [classes.active]: source.data.active })}
      >
        <div class={classes.infoAndButtons}>
          <div class={classes.info}>
            <div class={classes.title}>
              {source.data.active && (
                <>
                  <img src={rssIcon} />{' '}
                </>
              )}
              “{source.data.title}”
            </div>
            <div class={classes.url}>
              {source.data.active ? 'Feed: ' : 'Source: '}
              <a href={source.data.url} target="_blank">
                {source.data.url}
              </a>
            </div>{' '}
            <div class={classes.lastUpdate}>
              {source.data.active ? 'Last update: ' : 'Imported: '}
              {source.data.lastUpdate ? niceTime(source.data.lastUpdate) : '?'}
              {source.data.active || (
                <small> (this source is not refreshed automatically)</small>
              )}
            </div>
          </div>
          <div class={classes.buttons}>
            <button
              class={classes.button}
              onClick={(e) => this.removeSource(source)}
            >
              ❌ Remove
            </button>
            <button
              class={classes.button}
              onClick={(e) => this.refreshSource(source)}
              title={
                source.data.type === 'embeddedJsonld'
                  ? `To refresh annotations embedded in a page, first open that page again.`
                  : undefined
              }
            >
              🗘 Refresh
              {source.data.type === 'embeddedJsonld' && (
                <>
                  {' '}
                  <img src={infoIcon} />
                </>
              )}
            </button>
          </div>
        </div>
        {withAnnotations && (
          <details class={classes.showAnnotations} open>
            <summary>Stored annotations from this source</summary>
            <div style="margin-left: 2em;">
              <AnnotationsList source={source.data} />
            </div>
          </details>
        )}
      </li>
    ));

    return (
      <div>
        {sourceList ? (
          <ul class={classes.sourceList}>{sourceList}</ul>
        ) : (
          <p>
            <i>Loading list of sources…</i>
          </p>
        )}
        <div style="display: flex; align-items: center;">
          <div style="flex-grow: 1;">
            Total number of annotations:{' '}
            {this.state.totalAnnotationCount ?? <i>'counting…'</i>}
          </div>
          <button
            class={classes.button}
            ref={this.refreshButton}
            onClick={this.refreshAll}
          >
            🗘 Refresh all sources
          </button>
        </div>
      </div>
    );
  }
}
