import React from 'react';
import { guid } from 'sync-ql';
import {
    ActionBasic,
    ActionCustom,
    ActionDelete,
    ActionInsert,
    ActionSave,
    ActionsHandler,
    ActionType
} from '../types/action.bar.type';
import { DataRow } from '../types/cell.type';
import { TableContext } from '../types/table.type';
import { DataTableCustomButton } from './action.custom';
import { DataTableDeleteButton } from './action.delete';
import { DataTableDownloadButton } from './action.download';
import { DataTableInsertButton } from './action.insert';
import { DataTableSaveButton } from './action.save';
import { DataTableSeparator } from './action.separator';
import { DataTableUploadButton } from './action.upload';

export interface DataTableToolBarProps {
    context: TableContext,
    onSave: () => void,
    onInsert: (row: DataRow) => void,
    onDelete: (rows: DataRow[]) => void,
}

export const DataTableToolBar: React.FC<DataTableToolBarProps> = ({ context, onSave, onInsert, onDelete }) => {
    const [processingAction] = React.useState<{ [key: string]: boolean }>({})
    const [forceUpdate, setForceUpdate] = React.useState(false);

    context.forceUpdateToolbar = () => {
        setForceUpdate(!forceUpdate);
    }
    const handleClick = (id: string, type: ActionType, handler: ActionsHandler) =>
        () => {
            if (handler) {
                processingAction[id] = true;
                context.forceUpdateToolbar();

                const removeKeyMark = (data: DataRow[]) => {
                    return data.map((modification: any) => {
                        if (modification) {
                            if (modification.$deleted) {
                                const result = { ...modification.$deleted };
                                {
                                    delete result['<key>']
                                }
                                return { $deleted: result }
                            }
                            const result = { ...modification };
                            {
                                delete result['<key>']
                            }
                            return result
                        }
                        return modification
                    });
                }

                switch (type) {
                    case 'save':
                        {
                            const contextModifications = Object.values(context.modifications).filter(x => x.changed);
                            const modifications = removeKeyMark(contextModifications.map(x => x.changed));

                            (handler as ActionSave)(modifications, success => {
                                processingAction[id] = false;
                                context.forceUpdateToolbar();

                                if (success) {
                                    for (let i = 0; i < modifications.length; i++) {
                                        const modification = modifications[i];

                                        if (!modification['$deleted']) {
                                            const key = contextModifications[i].changed['<key>'];

                                            if (key && context.modifications[key]) {
                                                context.modifications[key].changed = {
                                                    ...modification,
                                                    ['<key>']: contextModifications[i].changed['<key>']
                                                }
                                            }
                                        }
                                    }
                                    onSave();
                                }
                            })
                        }
                        break;
                    case 'insert':
                        (handler as ActionInsert)(
                            context.columns.map(c => ({ ...c } as any)), (success, row) => {
                                processingAction[id] = false;
                                context.forceUpdateToolbar();

                                if (success && row) {
                                    row = { ...row }

                                    if (!row['<key>']) {
                                        row['<key>'] = guid()
                                    }
                                    onInsert(row);
                                }
                            })
                        break;
                    case 'delete':
                        (handler as ActionDelete)(removeKeyMark(Object.values(context.selection)), success => {
                            processingAction[id] = false;
                            context.forceUpdateToolbar();

                            if (success) {
                                onDelete(Object.values(context.selection));
                            }
                        })
                        break;
                    case 'upload':
                        (handler as ActionBasic)(success => {
                            processingAction[id] = false;
                            context.forceUpdateToolbar();

                            if (success) {
                            }
                        })
                        break;
                    case 'download':
                        (handler as ActionBasic)(success => {
                            processingAction[id] = false;
                            context.forceUpdateToolbar();

                            if (success) {
                            }
                        })
                        break;
                    case 'custom':
                        (handler as ActionCustom)(removeKeyMark(Object.values(context.selection)), success => {
                            processingAction[id] = false;
                            context.forceUpdateToolbar();

                            if (success) {
                            }
                        })
                        break;
                }
            }
        }
    return (
        <>
            {
                context && context.actions && context.actions.map(action => {
                    switch (action.type) {
                        case 'save':
                            return (
                                <DataTableSaveButton
                                    key={action.id}
                                    tooltip={action.tooltip}
                                    icon={action.icon}
                                    processing={!!processingAction[action.id]}
                                    disabled={!!action.disabled || Object.keys(context.modifications).length === 0}
                                    onClick={handleClick(action.id, action.type, action.handler)} />
                            )
                        case 'insert':
                            return (
                                <DataTableInsertButton
                                    key={action.id}
                                    tooltip={action.tooltip}
                                    icon={action.icon}
                                    processing={!!processingAction[action.id]}
                                    disabled={!!action.disabled}
                                    onClick={handleClick(action.id, action.type, action.handler)} />
                            )
                        case 'delete':
                            return (
                                <DataTableDeleteButton
                                    key={action.id}
                                    tooltip={action.tooltip}
                                    icon={action.icon}
                                    processing={!!processingAction[action.id]}
                                    disabled={!!action.disabled || Object.keys(context.selection).length === 0}
                                    onClick={handleClick(action.id, action.type, action.handler)} />
                            )
                        case 'download':
                            return (
                                <DataTableDownloadButton
                                    key={action.id}
                                    tooltip={action.tooltip}
                                    icon={action.icon}
                                    processing={!!processingAction[action.id]}
                                    disabled={!!action.disabled}
                                    onClick={handleClick(action.id, action.type, action.handler)} />
                            )
                        case 'upload':
                            return (
                                <DataTableUploadButton
                                    key={action.id}
                                    tooltip={action.tooltip}
                                    icon={action.icon}
                                    processing={!!processingAction[action.id]}
                                    disabled={!!action.disabled}
                                    onClick={handleClick(action.id, action.type, action.handler)} />
                            )
                        case 'custom':
                            return (
                                <DataTableCustomButton
                                    key={action.id}
                                    tooltip={action.tooltip}
                                    icon={action.icon}
                                    processing={!!processingAction[action.id]}
                                    disabled={!!action.disabled}
                                    onClick={handleClick(action.id, action.type, action.handler)} />
                            )
                        case 'separator':
                            return (
                                <DataTableSeparator key={action.id} />
                            )
                        default:
                            return (
                                <React.Fragment key={action.id} />
                            )
                    }
                })
            }
        </>
    )
}