import * as React from 'react';
import { useRef, useState } from "react";
import DataTable, { TableColumn, TableProps } from "react-data-table-component";

import { RaonkUpload } from 'raonkupload-react';

declare let RAONKUPLOAD: any;

const kuploadId = 'kupload1';

type DataTableCellProps<T extends WithId> = {
  row: T;
  rowIndex: number;
  col: TableColumn<T>;
  onChange: (row: T, field: keyof T, value: string) => void;
  columnKey: keyof T;
};

const getDataFromSelector = <T extends unknown>(
  row: T,
  rowIndex: number,
  col: TableColumn<T>
): string => {
  if (!col.selector) {
    return "";
  } else if (typeof col.selector !== "function") {
    // the ReactDataTable API allows the use of a string as the selector
    // but has deprecated it. We will disallow it.
    throw new Error("selector must be a a function (e.g. row => row.field");
  } else {
    return col.selector(row, rowIndex) as string;
  }
};

/**
 * A basic DataTableCell for a ReactDataTable. Assumptions are made
 * around the type of the data in the cell, namely that it is
 * string data.
 */
const DataTableCell = <T extends WithId>({
  row,
  rowIndex,
  col,
  onChange,
  columnKey
}: DataTableCellProps<T>) => {
  const [value, setValue] = useState<string>(
    getDataFromSelector(row, rowIndex, col)
  );
  const [editing, setEditing] = useState(false);

  const onBlur = () => {
    onChange(row, columnKey, value);
    setEditing(false);
  };

  if (editing) {
    return (
      <input
        autoFocus
        data-tag="allowRowEvents"
        type={"text"}
        className="form-control"
        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
          setValue(e.target.value);
        }}
        onBlur={onBlur}
        value={value as string}
      />
    );
  }

  return (
    <div className="data-table-cell" onClick={() => setEditing(true)}>
      {getDataFromSelector(row, rowIndex, col)}
    </div>
  );
};

export type WithId = {
  id: number;
  fileName: string;
  fileSize: string;
  fileFullPath: string;
  fileCustomValue: string;
  fileStatus: string;
};

export type DataTableColumn<T extends WithId> = TableColumn<T> & {
  editKey?: keyof T;
};

export type DataTableProps<T extends WithId> = Omit<
  TableProps<T>,
  "columns"
> & {
  columns: DataTableColumn<T>[];
  update: (ts: T[]) => void;
};

// adding this to see about hacking in a work around
const DataTableWithKUpload = <T extends WithId>(props: DataTableProps<T>) => {
  const [selected, setSelected] = useState(new Set<number>());
  const [toggleCleared, setToggleCleared] = useState(false);
  const newId = useRef(-1);

  const update = (m: T, field: keyof T, value: string) => {
    const editData = { ...m, [field]: value };
    const d = props.data.map((d) => (d.id === editData?.id ? editData : d));
    props.update(d);
  };

  const onSelectionChange = (selected: {
    allSelected: boolean;
    selectedCount: number;
    selectedRows: T[];
  }) => {
    const selection = new Set(selected.selectedRows.map((r) => r.id));
    setSelected(selection);
  };

  const deleteSelected = () => {
    const _d = props.data.filter((a) => !selected.has(a.id));
    setSelected(new Set());
    setToggleCleared(!toggleCleared);

    props.update(_d);
  };

  const downloadSelected = () => {
    const _d = props.data.filter((a) => selected.has(a.id));

    RAONKUPLOAD.ResetUpload(kuploadId);

    _d.forEach(file => {
      RAONKUPLOAD.AddUploadedFile(file.id, file.fileName, file.fileFullPath, file.fileSize, file.id, kuploadId);
    })

    RAONKUPLOAD.DownloadAllFile(kuploadId);
  };

  const contextActions = (
    <>
      <button key="download" onClick={downloadSelected}>
        Download
      </button>
      <span style={{width: "10px"} }></span>
      <button key="delete" onClick={deleteSelected}>
        Delete
      </button>
    </>
  );

  const dataTableColumns = () => {
    return props.columns.map((col) =>
      col.editKey ? { ...col} : col
    );
  };

  // RAONKUPLOAD Integrations
  const handleOpenFileDialog = () => {
    // props scope issue
    RAONKUPLOAD._G_PROPS = props;
    
    RAONKUPLOAD.ResetUpload(kuploadId);
    RAONKUPLOAD.OpenFileDialog(kuploadId);
  };

  const handleTransfer = () => {
    // props scope issue
    RAONKUPLOAD._G_PROPS = props;

    RAONKUPLOAD.ResetUpload(kuploadId);

    const _uploadFileLists = [...props.data].filter(file => file.fileStatus === 'Ready');

    const _arrLocalFileInfo: { path: string; customValue: string }[] = [];

    _uploadFileLists.forEach( (localFileInfo: { fileFullPath: string; fileCustomValue: string; }) => {
      _arrLocalFileInfo.push({
        path: localFileInfo.fileFullPath,
        customValue: localFileInfo.fileCustomValue
      });
    } );

    const _kuploadConfig = RAONKUPLOAD.GetUploadByName(kuploadId)._config;
    let _restoreConfig = false;
    (_kuploadConfig.useAfterAddEvent === '1') && (_kuploadConfig.useAfterAddEvent = '0', _restoreConfig = true);

    RAONKUPLOAD.AddLocalFileDirectlyEx(_arrLocalFileInfo, function() {
      _restoreConfig && (_kuploadConfig.useAfterAddEvent = '1');
      RAONKUPLOAD.Transfer(kuploadId);
    }, kuploadId);

  };
  
  const handleAfterAddFile = (eventParams:any) => {
    newId.current = RAONKUPLOAD._G_PROPS.data.length;

    const _addData = {
      id: newId.current,
      fileName: eventParams.eventInfo.paramObj.strName,
      fileSize: eventParams.eventInfo.paramObj.nSize,
      fileFullPath: eventParams.eventInfo.paramObj.strPath,
      fileCustomValue: newId.current + '',
      fileStatus: 'Ready'
    };

    const _d = [...RAONKUPLOAD._G_PROPS.data];
    _d.push(_addData);
    RAONKUPLOAD._G_PROPS.data.push(_addData); // for current scope

    RAONKUPLOAD._G_PROPS.update(_d);
	};

  const handleUploadComplete = (eventParams:any) => {
    const _uploadInfo = RAONKUPLOAD.GetListInfo('array', kuploadId);
    if(_uploadInfo.newFile) {
      _uploadInfo.newFile.forEach((newFileInfo: { originalName: string; uploadPath: string; size: string; customValue: string; }) => {
        updateComplete({
          id: parseInt(newFileInfo.customValue),
          fileName: newFileInfo.originalName,
          fileFullPath: newFileInfo.uploadPath,
          fileSize: newFileInfo.size,
          fileCustomValue: newFileInfo.customValue,
          fileStatus: 'Done'
        });
      })
    }
	};

  const updateComplete = (m: any) => {
    const _editData = { ...m};
    const _d = RAONKUPLOAD._G_PROPS.data.map((d: { id: any; }) => (d.id === _editData?.id ? _editData : d));
    
    RAONKUPLOAD._G_PROPS.data[m.id] = m; // for current scope
    RAONKUPLOAD._G_PROPS.update(_d);
  };

  const handleTest = () => {
    console.log(props);
  };

  return (
    <div>
      <DataTable
        {...props}
        columns={dataTableColumns()}
        data={props.data}
        selectableRows
        onSelectedRowsChange={onSelectionChange}
        clearSelectedRows={toggleCleared}
        actions={<div><button onClick={handleTest} style={{display: 'none'}}>Test props</button><span style={{padding: "5px"} }></span><button onClick={handleOpenFileDialog}>Add New</button><span style={{padding: "5px"} }></span><button onClick={handleTransfer}>Transfer</button></div>}
        contextActions={contextActions}
      />

      <RaonkUpload 
          debug={false}
          id={kuploadId}
          
          mode='edit'
          runtimes='agent'
          componentUrl="/raonkupload/js/raonkupload.js"
          config={{ 
            MaxTotalFileSize:'100GB',
            MaxOneFileSize:'1GB', 
            HandlerUrl:'http://localhost:8080/raonkupload/kupload/handler/raonkhandler.jsp', // Target url
            FolderNameRule: '/',
            InitVisible: false // Display screen
          }}

          onAfterAddFile={handleAfterAddFile}
          onUploadComplete={handleUploadComplete}
        />
    </div>
  );
};

export default DataTableWithKUpload;
