import { PanelOptions, TaskTableRowConfig, DatasourceTableRowConfig } from '../types';

import { Table, Button, HorizontalGroup, Modal } from '@grafana/ui';
import { getBackendSrv } from '@grafana/runtime';

import {
  PanelProps,
  toDataFrame,
  FieldType,
  applyFieldOverrides,
  createTheme,
  DataFrame,
  DataLinkClickEvent,
} from '@grafana/data';

import React, { useState } from 'react';
import * as _ from 'lodash';

interface Props extends PanelProps<PanelOptions> {}

export function Panel({ options, data, width, height, timeRange, onChangeTimeRange }: Props) {
  const taskConfigs: TaskTableRowConfig[] = [];
  const [tasks, setTasks] = useState(taskConfigs);
  const tasksDataFrame = getDataFrameForTaskTable(tasks, setTasks);

  const datasourceConfigs: DatasourceTableRowConfig[] = [];
  const [datasources, setDatasources] = useState(datasourceConfigs);
  const datasourceDataFrame = getDataFrameForDatasourceTable(datasources, setDatasources);

  const [isModalOpen, setModalVisibility] = useState(false);

  const timestampRange: [number, number] = [timeRange.from.unix(), timeRange.to.unix()];
  const backendSrv = getBackendSrv();
  // @ts-ignore
  backendSrv.getInspectorStream().subscribe({
    next: (resp: any) => {
      const queries = resp?.config?.data?.queries;
      if (_.isEmpty(queries)) {
        return;
      }

      const datasource = queries[0].datasource.type;
      const refId = queries[0].refId;
      const rawSql = queries[0].rawSql;
      const uid = queries[0].datasource.uid;

      const isDatasourceExist = _.some(
        datasources,
        (ds: DatasourceTableRowConfig) =>
          ds.datasource === datasource && ds.refId === refId && _.isEqual(ds.rawSql, rawSql) && ds.uid === uid
      );
      if (isDatasourceExist) {
        return;
      }

      const newConfig = createDatasourceConfig({ datasource, refId, rawSql, uid }, timestampRange);
      setDatasources([...datasources, newConfig]);
    },
  });

  function onAddTaskClick(): void {
    const selectedDatasources = _.filter(datasources, (datasource: DatasourceTableRowConfig) => datasource.select);
    const newTasks = _.map(selectedDatasources, (datasource: DatasourceTableRowConfig) =>
      createTaskFromDatasource(datasource)
    );
    setTasks([...tasks, ...newTasks]);
    onCloseModal();
    unselectAllDatasources();
  }

  function unselectAllDatasources(): void {
    const updatedDatasources = _.clone(datasources);
    for (const ds of updatedDatasources) {
      ds.select = false;
    }
    setDatasources(updatedDatasources);
  }

  function openModal(): void {
    setModalVisibility(true);
  }

  function onCloseModal(): void {
    setModalVisibility(false);
    unselectAllDatasources();
  }

  return (
    <div>
      <Table width={width} height={height - 40} data={tasksDataFrame} />
      <HorizontalGroup justify="flex-end">
        <Button
          variant="primary"
          aria-label="Add task button"
          icon="plus"
          style={{ marginTop: '8px' }}
          onClick={openModal}
        >
          Add Task
        </Button>
        <Modal title="Select Datasources" isOpen={isModalOpen} onDismiss={onCloseModal}>
          <Table width={width / 2 - 20} height={height - 40} data={datasourceDataFrame} />
          <HorizontalGroup justify="flex-end">
            <Button
              variant="primary"
              aria-label="Export data button"
              style={{ marginTop: '8px' }}
              onClick={onAddTaskClick}
            >
              Export data
            </Button>
          </HorizontalGroup>
        </Modal>
      </HorizontalGroup>
    </div>
  );
}

function getDataFrameForTaskTable(configs: TaskTableRowConfig[], setTasks: any): DataFrame {
  const dataFrame = toDataFrame({
    name: 'A',
    fields: [
      {
        name: 'Time',
        type: FieldType.number,
        values: _.map(configs, (config) => convertTimestampToDate(config.timestamp)),
      },
      {
        name: 'User',
        type: FieldType.string,
        values: _.map(configs, (config) => config.user),
      },
      {
        name: 'Datasource',
        type: FieldType.string,
        values: _.map(configs, (config) => config.datasource),
      },
      {
        name: 'Exported Rows',
        type: FieldType.number,
        values: _.map(configs, (config) => config.rowsCount),
      },
      {
        name: 'Progress',
        type: FieldType.string,
        values: _.map(configs, (config) => `${config.progress}%`),
      },
      {
        name: 'Status',
        type: FieldType.string,
        values: _.map(configs, (config) => config.status),
      },
      {
        name: 'Download CSV',
        type: FieldType.string,
        values: _.map(configs, (config) => `data:image/png;base64,${DOWNLOAD_ICON_BASE_64}`),
        config: {
          custom: {
            filterable: false,
            displayMode: 'image',
          },
          links: [
            {
              targetBlank: false,
              title: 'CSV link',
              url: 'https://chartwerk.io/',
            },
          ],
        },
      },
      {
        name: 'Delete task',
        type: FieldType.string,
        values: _.map(configs, (config) => `data:image/png;base64,${CLOSE_ICON_BASE_64}`),
        config: {
          custom: {
            filterable: false,
            displayMode: 'image',
          },
          links: [
            {
              targetBlank: false,
              title: 'Delete',
              url: '#',
              onClick: (event: DataLinkClickEvent) => onDeleteClick(event, configs, setTasks),
            },
          ],
        },
      },
    ],
  });

  const dataFrames = applyFieldOverrides({
    data: [dataFrame],
    fieldConfig: {
      overrides: [],
      defaults: {},
    },
    theme: createTheme(),
    replaceVariables: (value: string) => value,
  });
  return dataFrames[0];
}

function getDataFrameForDatasourceTable(configs: DatasourceTableRowConfig[], setDatasources: any): DataFrame {
  const dataFrame = toDataFrame({
    name: 'A',
    fields: [
      {
        name: 'Select',
        type: FieldType.string,
        values: _.map(
          configs,
          (config) => `data:image/svg+xml;base64,${config.select ? SELECT_ICON_BASE_64 : UNSELECT_ICON_BASE_64}`
        ),
        config: {
          custom: {
            filterable: false,
            displayMode: 'image',
          },
          links: [
            {
              targetBlank: false,
              title: 'Select',
              url: '#',
              onClick: (event: DataLinkClickEvent) => onDatasourceSelectClick(event, configs, setDatasources),
            },
          ],
        },
      },
      {
        name: 'Panel',
        type: FieldType.string,
        values: _.map(configs, (config) => config.panel),
      },
      {
        name: 'RefId',
        type: FieldType.string,
        values: _.map(configs, (config) => config.refId),
      },
      {
        name: 'Datasource',
        type: FieldType.string,
        values: _.map(configs, (config) => config.datasource),
      },
    ],
  });

  const dataFrames = applyFieldOverrides({
    data: [dataFrame],
    fieldConfig: {
      overrides: [],
      defaults: {},
    },
    theme: createTheme(),
    replaceVariables: (value: string) => value,
  });
  return dataFrames[0];
}

function onDeleteClick(e: DataLinkClickEvent, tasks: TaskTableRowConfig[], setTasks: any): void {
  const rowIndex = e.origin.rowIndex;
  const filteredTasks = _.filter(tasks, (task, idx) => idx !== rowIndex);
  setTasks(filteredTasks);
}

function onDatasourceSelectClick(
  e: DataLinkClickEvent,
  datasources: DatasourceTableRowConfig[],
  setDatasources: any
): void {
  const rowIndex = e.origin.rowIndex;
  const updatedDatasources = _.clone(datasources);
  updatedDatasources[rowIndex].select = !updatedDatasources[rowIndex].select;
  setDatasources(updatedDatasources);
}

function createTaskFromDatasource(config: DatasourceTableRowConfig): TaskTableRowConfig {
  return {
    timestamp: Date.now(),
    user: 'admin',
    datasource: config.datasource,
    rowsCount: 3214,
    progress: 100,
    status: 'finished',
  };
}

function createDatasourceConfig(obj: any, timerange: [number, number]): DatasourceTableRowConfig {
  return {
    select: false,
    panel: 'Panel',
    refId: obj.refId,
    datasource: obj.datasource,
    rawSql: obj.rawSql,
    uid: obj.uid,
    timerange,
  };
}

function convertTimestampToDate(timestamp: number): string {
  const options: Intl.DateTimeFormatOptions = {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: 'numeric',
    minute: 'numeric',
    second: 'numeric',
  };
  return new Date(timestamp).toLocaleString('en-GB', options);
}

const CLOSE_ICON_BASE_64 =
  'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACJSURBVHgB7ZPRCcAgDESv0lWc0zhC53OIjmAVUpCSamL76YEoyfFIiAGWfldK6SwnKHyhep9xJ3iPcqgH5RyxV1VlBWYJypXVHMEiCaqBbRhAy3W3B76j954wq6ZSVZsOY+WXt6i9l2ymGTlUq0VpOcIqaQC96Zth01DN1zBBefVI4SNp9Za+6wLcH6DKFrfpxgAAAABJRU5ErkJggg==';
const DOWNLOAD_ICON_BASE_64 =
  'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADlSURBVHgB3ZPNDYJAEIVnN96lBA7A2RIsATuQiiwBSrAD7MAjCZBACXqFwPomMRtEwMVwgZeQhfn5mNnMEG1CaZoeiqKwTWJ3JkFCiEtVVU+8+r9iJRlKSrk3iqOFtWJglmXHf3yDwCRJbBxxnudh34cRYluMMbKGcgWNCIlnjEuIJ1JK2WzDWeKb7YHjONEsYBf6kTABY+mWuYX+3Xiex9UFU7D3FllfwLqueQvi/h8ZCtBprDLY703T6A0yWj2ArmSoxedQV4jSSz5xj4pmCi0/NKfrwNz5bdtaNENciOu6N1qNXhzZXHMb9Q+nAAAAAElFTkSuQmCC';
const UNSELECT_ICON_BASE_64 =
  'PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMC41IiB5PSIwLjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjEuNSIgZmlsbD0iIzExMTIxNiIgc3Ryb2tlPSIjMkQyRTM0Ii8+Cjwvc3ZnPgo=';
const SELECT_ICON_BASE_64 =
  'PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiByeD0iMiIgZmlsbD0iIzRBNzFEMiIvPgo8cGF0aCBkPSJNNS45ODI2NCAxMi41MjE3QzUuNzczOTUgMTIuNTIxNyA1LjU4MjY0IDEyLjQ1MjIgNS40MjYxMiAxMi4yOTU2TDEuOTY1MjUgOC44MzQ3NkMxLjY1MjIxIDguNTIxNzIgMS42NTIyMSA4LjAzNDc2IDEuOTY1MjUgNy43MjE3MkMyLjI3ODI5IDcuNDA4NjcgMi43NjUyNSA3LjQwODY3IDMuMDc4MjkgNy43MjE3Mkw2LjAwMDAzIDEwLjYyNjFMMTIuOTM5MiAzLjcwNDMzQzEzLjI1MjIgMy4zOTEyOCAxMy43MzkyIDMuMzkxMjggMTQuMDUyMiAzLjcwNDMzQzE0LjM2NTMgNC4wMTczNyAxNC4zNjUzIDQuNTA0MzMgMTQuMDUyMiA0LjgxNzM3TDYuNTU2NTYgMTIuMjk1NkM2LjM4MjY0IDEyLjQ1MjIgNi4xOTEzNCAxMi41MjE3IDUuOTgyNjQgMTIuNTIxN1YxMi41MjE3WiIgZmlsbD0iI0ZFRkZGRiIvPgo8L3N2Zz4K';
