/**
 * Copyright 2019 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { h, Component, FunctionalComponent } from 'preact';
import { Result, Topics, Champions } from 'shared/state';
import {
  getResultLabel,
  getResultTopic,
  getResultChampionName,
  fetchJSON,
  escapePatchPathComponent,
} from 'client/utils';
import Select from '../../select';

interface Props {
  topics: Topics;
  champions: Champions;
  path: string;
  result?: Result;
  onShowSlides: (url: string) => void;
  onCreateVote: () => void;
}

const AdminSelectedBracketWrapper: FunctionalComponent<{}> = ({ children }) => (
  <section>
    <h1>Selected bracket</h1>
    {children}
  </section>
);

const TopicsSelect: FunctionalComponent<{
  value: string;
  topics: Topics;
  onInput: (event: Event) => void;
}> = ({ onInput, topics, value }) => {
  const sortedTopics = Object.entries(topics).sort((a, b) =>
    a[1].label > b[1].label ? 1 : -1,
  );

  return (
    <Select onInput={onInput} value={value}>
      <option value=""></option>
      {sortedTopics.map(([id, topic]) => (
        <option value={id}>{topic.label}</option>
      ))}
    </Select>
  );
};

export default class AdminSelectedBracket extends Component<Props> {
  private _onTopicSelect = (event: Event) => {
    const el = event.currentTarget as HTMLSelectElement;
    const container = el.closest('.admin-form-item') as HTMLElement;

    fetchJSON('/admin/patch', {
      method: 'PATCH',
      body: [
        {
          op: 'replace',
          path: `/results${this.props.path}/items/${Number(
            container.dataset.itemIndex,
          )}`,
          value: el.value,
        },
      ],
    });
  };

  private _onChampionSelect = (event: Event) => {
    const el = event.currentTarget as HTMLSelectElement;
    const container = el.closest('.admin-form-item') as HTMLElement;
    const topicId = this.props.result!.items[
      Number(container.dataset.itemIndex)
    ];

    fetchJSON('/admin/patch', {
      method: 'PATCH',
      body: [
        {
          op: 'replace',
          path: `/topics/${escapePatchPathComponent(
            topicId as string,
          )}/championId`,
          value: el.value,
        },
      ],
    });
  };

  private _setWinner(index: number) {
    const path = this.props.path === '/' ? '' : this.props.path;

    fetchJSON('/admin/patch', {
      method: 'PATCH',
      body: [
        {
          op: 'replace',
          path: `/results${path}/winningIndex`,
          value: index,
        },
      ],
    });
  }

  private _onWinnerSelect = (event: Event) => {
    const el = event.currentTarget as HTMLSelectElement;
    const container = el.closest('.admin-form-item') as HTMLElement;
    this._setWinner(Number(container.dataset.itemIndex));
  };

  private _onShowSlides = (event: Event) => {
    const el = event.currentTarget as HTMLSelectElement;
    const container = el.closest('.admin-form-item') as HTMLElement;
    const index = Number(container.dataset.itemIndex);
    const topic = getResultTopic(
      this.props.topics,
      this.props.result!.items[index],
    );
    this.props.onShowSlides(topic!.slidesURL);
  };

  private _onClearWinner = () => {
    this._setWinner(-1);
  };

  private _onCreateVote = () => {
    this.props.onCreateVote();
  };

  private _onZoomHere = () => {
    let toHighlight: string[];

    if (this.props.path === '/') {
      toHighlight = ['0', '1'];
    } else {
      const parentPath = this.props.path
        .split('/items/')
        .slice(1)
        .join('-');

      toHighlight = [parentPath, parentPath + '-0', parentPath + '-1'];
    }

    fetchJSON('/admin/patch', {
      method: 'PATCH',
      body: [
        {
          op: 'replace',
          path: `/bracketZoom`,
          value: toHighlight,
        },
      ],
    });
  };

  render({ result, topics, champions }: Props) {
    if (!result) {
      return (
        <AdminSelectedBracketWrapper>
          <p>No bracket item selected</p>
        </AdminSelectedBracketWrapper>
      );
    }
    return (
      <AdminSelectedBracketWrapper>
        <div class="admin-form-items">
          {result.items.map((item, i) => {
            const isLeaf = typeof item === 'string';
            const topic = getResultTopic(topics, item);

            const topicAndChamp = isLeaf
              ? [
                  <div>
                    <label>
                      <span class="label">Topic</span>
                      <TopicsSelect
                        value={item as string}
                        topics={topics}
                        onInput={this._onTopicSelect}
                      />
                    </label>
                  </div>,
                  <div>
                    <label>
                      <span class="label">Champion</span>
                      <Select
                        disabled={!topic}
                        value={topic ? topic.championId : ''}
                        onInput={this._onChampionSelect}
                      >
                        <option value="">{topic ? 'None' : ''}</option>
                        {Object.entries(champions).map(([id, champion]) => (
                          <option value={id}>{champion.name}</option>
                        ))}
                      </Select>
                    </label>
                  </div>,
                ]
              : [
                  <div>
                    <span class="label">Topic</span>{' '}
                    <span class="prefilled-input">
                      {getResultLabel(topics, item) || 'Pending'}
                    </span>
                  </div>,
                  <div>
                    <span class="label">Champion</span>{' '}
                    <span class="prefilled-input">
                      {getResultChampionName(topics, item, champions) ||
                        'Pending'}
                    </span>
                  </div>,
                ];

            return (
              <div class="admin-form-item" data-item-index={i}>
                {topicAndChamp}
                <div>
                  <button
                    class="button"
                    disabled={result.winningIndex === i}
                    onClick={this._onWinnerSelect}
                  >
                    Set as winner
                  </button>{' '}
                  {topic && topic.slidesURL && (
                    <button class="button" onClick={this._onShowSlides}>
                      Show slides
                    </button>
                  )}
                </div>
              </div>
            );
          })}
          <div class="admin-form-extras">
            <div class="label">Actions</div>
            <div>
              <button
                class="button"
                disabled={result.winningIndex === -1}
                onClick={this._onClearWinner}
              >
                Clear winner
              </button>{' '}
              <button class="button" onClick={this._onCreateVote}>
                Create vote
              </button>{' '}
              <button class="button" onClick={this._onZoomHere}>
                Zoom here
              </button>
            </div>
          </div>
        </div>
      </AdminSelectedBracketWrapper>
    );
  }
}