import React, { Component } from "react";
import deepFind from "../../utils/deepfind";
import Column from "./columns";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faBook, faBookJournalWhills, faEdit, faTrash } from "@fortawesome/free-solid-svg-icons";
import { Link } from "react-router-dom";
import ConfirmButton from "./ConfirmButton";
import { Buffer } from 'buffer';
import Button, { ButtonType } from "./Button";
import { DateView } from "./DateView";

export interface AuditParams{
    entityName : string,
    primaryKey : string
}

export interface TableBodyProps<T>{
    data : T[] | undefined;
    keyName : string;
    columns : Column<T>[];
    editPath? : string;
    selectedRow? : T;
    canEdit? :  ( item : T ) => boolean;
    canDelete? : ( item : T ) => boolean;
    onDelete?: ( item? : T ) => void;
    onAuditParams?: ( item : T ) => AuditParams;
    onSelectRow? : ( item : T ) => void;
    showSecondaryAudit : boolean;
}

class TableBody<T> extends Component<TableBodyProps<T>> {
    resolvePath = ( path : string, args : string[]) => {
        let modifiedPath = path;

        let index : number = 0;
        while ( index < args.length )
        {        
            modifiedPath = modifiedPath.replace("{"+index+"}", args[index])
            index++;
        }
        
        return modifiedPath;
    }

    renderCell = (item : T, column : Column<T>) => {
        const {keyName} = this.props;
        if (column.content) return column.content(item);

        const foundItem = deepFind(item, column.path || column.key)        

        let columnContent : JSX.Element;

        if (foundItem instanceof Date)        {
            columnContent = <DateView value={foundItem}/>
        }
        else if (typeof foundItem === "object"){
            columnContent = <></>;
        }
        else {
            columnContent = <>
                {foundItem}
            </>;
        }

        const linkPath = column.link;

        if (linkPath !== undefined){
            const resolvedlinkPath = this.resolvePath( linkPath, [ (item as any)[keyName] ] );
            columnContent = <Link to={resolvedlinkPath}>{columnContent}</Link>;
        }

        return  <>
                    {columnContent}
                </>;
    };

    clickRow = ( value : T ) =>
    {
        const { onSelectRow } = this.props;

        if (onSelectRow !== undefined)
            onSelectRow( value );            
    }

    createKey = (item : T, column : Column<T>) => {
         const { keyName } = this.props;

         return (item as any)[keyName] + '_' + (column.path || column.key);
    };
    
    handleAuditParams = ( item : T, primaryOnly : boolean ) => {
        const { onAuditParams } = this.props;        
        if (onAuditParams !== undefined) {
            var auditParams = onAuditParams(item);            
            let json = JSON.stringify(auditParams);
            var params = Buffer.from(json).toString('base64') ;

            var queryString = "";
            if (primaryOnly===false)
                queryString += "?primaryOnly=" + primaryOnly;

            return "/audit/" + params + queryString;
        }
        
        return "";
    }

    render() {
        const { data, keyName, selectedRow, columns, editPath, canEdit, canDelete, onDelete, onAuditParams, showSecondaryAudit } = this.props;
        const showDelete:boolean = onDelete != null;
        const showEdit:boolean = (editPath != null) && (editPath !== "");        
        const showAudit:boolean = onAuditParams !== undefined;

        return (
            <tbody>
                {data?.map((item) => {
                    let classNames = "";
                    if (selectedRow === item)
                    {
                        classNames+="table-primary";
                    }

                   return (<tr className={classNames} key={(item as any)[keyName]}>
                        {columns.map((column) => (
                           <td key={this.createKey(item, column)} onClick={ () => this.clickRow(item)}>{this.renderCell(item, column)}</td>
                        ))}
                        {showEdit  && <td className="align-middle">{(canEdit === undefined || canEdit(item)) && <Button buttonType={ButtonType.primary} to={this.resolvePath( editPath!, [ (item as any)[keyName] ] )}><FontAwesomeIcon icon={faEdit}/></Button>}</td>}
                        {showDelete && <td className="align-middle">{(canDelete === undefined || canDelete(item)) && <ConfirmButton buttonType={ButtonType.primary} keyValue={item} onClick={onDelete} confirmMessage={"Press again to delete"} ><FontAwesomeIcon icon={faTrash}/></ConfirmButton>}</td>}
                        {showAudit && <td className="align-middle"><Link to={this.handleAuditParams(item, true)}><Button buttonType={ButtonType.primary}><FontAwesomeIcon icon={faBook}/></Button></Link></td>}
                        {showAudit && showSecondaryAudit && <td className="align-middle"><Link to={this.handleAuditParams(item, false)}><Button buttonType={ButtonType.secondary}><FontAwesomeIcon icon={faBookJournalWhills}/></Button></Link></td>}
                   </tr>)
                })}
            </tbody>
        );
    }
}

export default TableBody;
