import React, { useRef, useState } from "react";
import { useSortBy, useTable, useFilters, useGlobalFilter, useAsyncDebounce, usePagination, useRowSelect, useColumnOrder } from 'react-table'
import matchSorter from 'match-sorter'
import _ from 'lodash';
import moment from 'moment';
import { useHistory } from "react-router-dom";
import { OverlayPanel } from 'primereact/overlaypanel';
//import {InputSwitch} from 'primereact/inputswitch';
import { InputText } from 'primereact/inputtext';
import { Calendar } from 'primereact/calendar';
import { Paginator } from 'primereact/paginator';
import { TriStateCheckbox } from 'primereact/tristatecheckbox';
import { Slider } from 'primereact/slider';
import { Button } from "react-bootstrap";
import { Link } from "react-router-dom";
import { InputNumber } from "primereact/inputnumber";
import { MultiSelect } from 'primereact/multiselect';
import { RadioButton } from 'primereact/radiobutton';
import { useExportData } from "react-table-plugins";
import UIConstants from '../utils/ui.constants';
import Papa from "papaparse";
import JsPDF from "jspdf";
import "jspdf-autotable";

let tbldata = [], filteredData = [];
let selectedRows = [];
let isunittest = false;
let showTopTotal = true;
let showGlobalFilter = true;
let showColumnFilter = true;
let allowColumnSelection = true;
let allowRowSelection = false;
let columnclassname = [];
let parentCallbackFunction, parentCBonSelection;
let showCSV = false;
let anyOfFilter = '';

// Define a default UI for filtering
function GlobalFilter({
  preGlobalFilteredRows,
  globalFilter,
  setGlobalFilter,
}) {
  const [value, setValue] = React.useState(globalFilter)
  const onChange = useAsyncDebounce(value => { setGlobalFilter(value || undefined) }, 200)
  return (
    <span style={{ marginLeft: "-10px" }}>
      <input
        value={value || ""}
        onChange={e => {
          setValue(e.target.value);
          onChange(e.target.value);
        }}
      /> {" "}<i className="fa fa-search"></i>
    </span>
  )
}


// Define a default UI for filtering
function DefaultColumnFilter({
  column: { filterValue, preFilteredRows, setFilter, filteredRows },
}) {
  const [value, setValue] = useState('');
  React.useEffect(() => {
    if (!filterValue && value) {
      setValue('');
    }
  }, [filterValue, value]);
  return (
    <div className="table-filter" onClick={e => { e.stopPropagation() }}>
      <input
        value={value}   //***TO REMOVE - INCOMING CHANGE WAS value={filterValue || ''}
        onChange={e => {
          setValue(e.target.value);
          setFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
        }}
      />
      {value && <i onClick={() => { setFilter(undefined); setValue('') }} className="table-reset fa fa-times" />}
    </div>
  )
}

/* 
Generate and download csv 
*/
function getExportFileBlob({ columns, data, fileType, fileName }) {
  if (fileType === "csv") {
    // CSV example
    const headerNames = columns.map((col) => col.exportValue);
    const csvString = Papa.unparse({ fields: headerNames, data });
    return new Blob([csvString], { type: "text/csv" });
  } //PDF example
  else if (fileType === "pdf") {
    const headerNames = columns.map((column) => column.exportValue);
    const doc = new JsPDF();
    var index = headerNames.indexOf('Action');
    if (index > -1) {
      headerNames.splice(index, 1);
    }
    doc.autoTable({
      head: [headerNames],
      body: data,
    });
    doc.save(`${fileName}.pdf`);
    return false;
  }
}

// This is a custom filter UI for selecting
// a unique option from a list
function SelectColumnFilter({
  column: { filterValue, setFilter, preFilteredRows, id },
}) {
  const [value, setValue] = useState('');
  React.useEffect(() => {
    if (!filterValue && value) {
      setValue('');
    }
  }, [filterValue, value]);
  const options = React.useMemo(() => {
    const options = new Set()
    preFilteredRows.forEach(row => {
      options.add(row.values[id])
    })
    return [...options.values()]
  }, [id, preFilteredRows])
  // Render a multi-select box
  return (
    <div onClick={e => { e.stopPropagation() }}>
      <select
        style={{
          height: '24.2014px',
          width: '60px',
          border: '1px solid lightgrey',
        }}
        value={value}
        onChange={e => {
          setValue(e.target.value);
          setFilter(e.target.value || undefined)
        }}
      >
        <option value="">All</option>
        {options.map((option, i) => (
          <option key={i} value={option}>
            {option}
          </option>
        ))}
      </select>
    </div>
  )
}

// Multi-Select Custom Filter and set unique options value
function MultiSelectColumnFilter({
  column: { filterValue, setFilter, preFilteredRows, id },
}) {
  const [value, setValue] = useState('');
  const [filtertype, setFiltertype] = useState('Any');
  // Set Any / All Filter type
  const setSelectTypeOption = (option) => {
    setFiltertype(option);
    anyOfFilter = option
    if (value !== '') {
      setFilter(value);
    }
  };

  React.useEffect(() => {
    if (!filterValue && value) {
      setValue('');
      setFiltertype('Any');
    }
  }, [filterValue, value, filtertype]);
  anyOfFilter = filtertype;
  const options = React.useMemo(() => {
    let options = new Set();
    preFilteredRows.forEach(row => {
      row.values[id].split(',').forEach(value => {
        if (value !== '') {
          let hasValue = false;
          options.forEach(option => {
            if (option.name === value) {
              hasValue = true;
            }
          });
          if (!hasValue) {
            let option = { 'name': value, 'value': value };
            options.add(option);
          }
        }
      });
    });
    return [...options.values()]
  }, [id, preFilteredRows]);

  // Render a multi-select box
  return (
    <div onClick={e => { e.stopPropagation() }} >
      <div className="p-field-radiobutton">
        <RadioButton inputId="filtertype1" name="filtertype" value="Any" onChange={(e) => setSelectTypeOption(e.value)} checked={filtertype === 'Any'} />
        <label htmlFor="filtertype1">Any</label>
      </div>
      <div className="p-field-radiobutton">
        <RadioButton inputId="filtertype2" name="filtertype" value="All" onChange={(e) => setSelectTypeOption(e.value)} checked={filtertype === 'All'} />
        <label htmlFor="filtertype2">All</label>
      </div>
      <div style={{ position: 'relative' }} >
        <MultiSelect data-testid="multi-select" id="multi-select" optionLabel="value" optionValue="value" filter={true}
          value={value}
          options={options}
          onChange={e => {
            setValue(e.target.value);
            setFilter(e.target.value || undefined, filtertype)
          }}
          className="multi-select"
        />
      </div>
    </div>
  )
}

// This is a custom filter UI that uses a
// slider to set the filter value between a column's
// min and max values
function SliderColumnFilter({
  column: { filterValue, setFilter, preFilteredRows, id },
}) {
  // Calculate the min and max
  // using the preFilteredRows
  const [value, setValue] = useState(0);
  /*const [min, max] = React.useMemo(() => {
    let min = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
    let max = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
    preFilteredRows.forEach(row => {
      min = Math.min(row.values[id], min)
      max = Math.max(row.values[id], max)
    })
    return [min, max]
  }, [id, preFilteredRows])*/

  return (
    <div onClick={e => { e.stopPropagation() }} className="table-slider">
      <Slider value={value} onChange={(e) => { setFilter(e.value); setValue(e.value) }} />
    </div>
  )
}

// This is a custom filter UI that uses a
// switch to set the value
function BooleanColumnFilter({
  column: { setFilter, filterValue },
}) {
  // Calculate the min and max
  // using the preFilteredRows
  const [value, setValue] = useState(null);
  React.useEffect(() => {
    if (!filterValue && value) {
      setValue(null);
    }
  }, [filterValue, value]);
  return (
    <div onClick={e => { e.stopPropagation() }}>
      <TriStateCheckbox value={value} style={{ 'width': '15px', 'height': '24.2014px' }} onChange={(e) => { setValue(e.value); setFilter(e.value === null ? undefined : e.value); }} />
    </div>
  )
}

// This is a custom filter UI that uses a
// calendar to set the value
function CalendarColumnFilter({
  column: { setFilter, filterValue },
}) {
  // Calculate the min and max
  // using the preFilteredRows
  const [value, setValue] = useState('');
  React.useEffect(() => {
    if (!filterValue && value) {
      setValue(null);
    }
  }, [filterValue, value]);
  return (

    <div className="table-filter" onClick={e => { e.stopPropagation() }}>
      <Calendar value={value} appendTo={document.body} dateFormat="yy-mm-dd" onChange={(e) => {
        const value = moment(e.value).format('YYYY-MM-DD')
        setValue(value); setFilter(value);
      }} showIcon></Calendar>
      {value && <i onClick={() => { setFilter(undefined); setValue('') }} className="tb-cal-reset fa fa-times" />}
    </div>
  )
}

// This is a custom filter UI that uses a
// calendar to set the value
function DateTimeColumnFilter({
  column: { setFilter, filterValue },
}) {
  const [value, setValue] = useState('');
  React.useEffect(() => {
    if (!filterValue && value) {
      setValue(null);
    }
  }, [filterValue, value]);
  return (

    <div className="table-filter" onClick={e => { e.stopPropagation() }}>
      <Calendar value={value} appendTo={document.body} dateFormat="yy/mm/dd" onChange={(e) => {
        const value = moment(e.value, moment.ISO_8601).format('YYYY-MM-DD HH:mm:ss')
        setValue(value); setFilter(value);
      }} showIcon
      // showTime= {true}
      //showSeconds= {true}
      // hourFormat= "24"
      ></Calendar>
      {value && <i onClick={() => { setFilter(undefined); setValue('') }} className="tb-cal-reset fa fa-times" />}
    </div>
  )
}

/**
 * Custom function to filter data from date field.
 * @param {Array} rows 
 * @param {String} id 
 * @param {String} filterValue 
 */
function fromDatetimeFilterFn(rows, id, filterValue) {
  const filteredRows = _.filter(rows, function (row) {
    // If cell value is null or empty
    if (!row.values[id]) {
      return false;
    }
    //Remove microsecond if value passed is UTC string in format "YYYY-MM-DDTHH:mm:ss.sssss"
    let rowValue = moment.utc(row.values[id].split('.')[0]);
    if (!rowValue.isValid()) {
      // For cell data in format 'YYYY-MMM-DD'
      rowValue = moment.utc(moment(row.values[id], 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS"));
    }
    const start = moment.utc(moment(filterValue, 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS"));

    return (start.isSameOrBefore(rowValue));
  });
  return filteredRows;
}

/**
 * Custom function to filter Multi selection based on filter type (Any/All) .
 * @param {Array} rows 
 * @param {String} id 
 * @param {String} filterValue 
 */
function multiSelectFilterFn(rows, id, filterValue) {
  if (filterValue) {
    const filteredRows = _.filter(rows, function (row) {
      if (filterValue.length === 0) {
        return true;
      }
      // If cell value is null or empty
      if (!row.values[id]) {
        return false;
      }
      let rowValue = row.values[id];
      let hasData = false;
      if (anyOfFilter === 'Any') {
        hasData = false;
        filterValue.forEach(filter => {
          if (rowValue.includes(filter)) {
            hasData = true;
          }
        });
      }
      else {
        hasData = true;
        filterValue.forEach(filter => {
          if (!rowValue.includes(filter)) {
            hasData = false;
          }
        });
      }
      return hasData;
    });
    return filteredRows;
  }
}

/**
 * Custom function to filter data from date field.
 * @param {Array} rows 
 * @param {String} id 
 * @param {String} filterValue 
 */
function toDatetimeFilterFn(rows, id, filterValue) {
  let end = moment.utc(moment(filterValue, 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS"));
  end = moment(end, "DD-MM-YYYY").add(1, 'days');
  const filteredRows = _.filter(rows, function (row) {
    // If cell value is null or empty
    if (!row.values[id]) {
      return false;
    }
    //Remove microsecond if value passed is UTC string in format "YYYY-MM-DDTHH:mm:ss.sssss"
    let rowValue = moment.utc(row.values[id].split('.')[0]);
    if (!rowValue.isValid()) {
      // For cell data in format 'YYYY-MMM-DD'
      rowValue = moment.utc(moment(row.values[id], 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS"));
    }
    return (end.isSameOrAfter(rowValue));
  });
  return filteredRows;
}

/**
 * Custom function to filter data from date field.
 * @param {Array} rows 
 * @param {String} id 
 * @param {String} filterValue 
 */
function dateFilterFn(rows, id, filterValue) {
  const filteredRows = _.filter(rows, function (row) {
    // If cell value is null or empty
    if (!row.values[id]) {
      return false;
    }
    //Remove microsecond if value passed is UTC string in format "YYYY-MM-DDTHH:mm:ss.sssss"
    let rowValue = moment.utc(row.values[id].split('.')[0]);
    if (!rowValue.isValid()) {
      // For cell data in format 'YYYY-MMM-DD'
      rowValue = moment.utc(moment(row.values[id], 'YYYY-MM-DD').format("YYYY-MM-DDT00:00:00"));
    }
    const start = moment.utc(moment(filterValue, 'YYYY-MM-DD').format("YYYY-MM-DDT00:00:00"));
    const end = moment.utc(moment(filterValue, 'YYYY-MM-DD').format("YYYY-MM-DDT23:59:59"));
    return (start.isSameOrBefore(rowValue) && end.isSameOrAfter(rowValue));
  });
  return filteredRows;
}

// This is a custom UI for our 'between' or number range
// filter. It uses slider to filter between min and max values.
function RangeColumnFilter({
  column: { filterValue = [], preFilteredRows, setFilter, id },
}) {
  const [min, max] = React.useMemo(() => {
    let min = 0;
    let max = 0;
    if (preFilteredRows.length > 0 && preFilteredRows[0].values[id]) {
      min = preFilteredRows[0].values[id];
    }
    preFilteredRows.forEach(row => {
      min = Math.min(row.values[id] ? row.values[id] : 0, min);
      max = Math.max(row.values[id] ? row.values[id] : 0, max);
    });
    return [min, max];
  }, [id, preFilteredRows]);
  if (filterValue.length === 0) {
    filterValue = [min, max];
  }

  return (
    <>
      <div className="filter-slider-label">
        <span style={{ float: "left" }}>{filterValue[0]}</span>
        <span style={{ float: "right" }}>{min !== max ? filterValue[1] : ""}</span>
      </div>
      <Slider value={filterValue} min={min} max={max} className="filter-slider"
        style={{}}
        onChange={(e) => { setFilter(e.value); }} range />
    </>
  );
}

// This is a custom UI for our 'between' or number range
// filter. It uses two number boxes and filters rows to
// ones that have values between the two
function NumberRangeColumnFilter({
  column: { filterValue = [], preFilteredRows, setFilter, id },
}) {
  const [errorProps, setErrorProps] = useState({});
  const [maxErr, setMaxErr] = useState(false);
  const [min, max] = React.useMemo(() => {
    let min = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
    let max = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
    preFilteredRows.forEach(row => {
      min = Math.min(row.values[id], min)
      max = Math.max(row.values[id], max)
    })
    return [min, max]
  }, [id, preFilteredRows])

  return (
    <div
      style={{
        //  display: 'flex',
        //  flexdirection:'column',
        alignItems: 'center'
      }}
    >
      <InputText
        value={filterValue[0]}
        type="number"
        onChange={e => {
          const val = e.target.value;
          setFilter((old = []) => [val ? parseFloat(val, 10) : undefined, old[1]]);
        }}
        placeholder={`Min (${min})`}
        style={{
          width: '55px',
          height: '25px'
          // marginRight: '0.5rem',
        }}
      />
      <InputText
        value={filterValue[1] || ''}
        type="number"
        {...errorProps}
        className={maxErr && 'field-error'}
        onChange={e => {
          const val = e.target.value;
          const minVal = filterValue.length && filterValue[0];
          if (minVal && e.target.value < minVal) {
            setMaxErr(true);
            setErrorProps({
              tooltip: "Max value should be greater than Min",
              tooltipOptions: { event: 'hover' }
            });
          } else {
            setMaxErr(false);
            setErrorProps({});
          }
          setFilter((old = []) => [old[0], val ? parseFloat(val, 10) : undefined])
        }}
        placeholder={`Max (${max})`}
        style={{
          width: '55px',
          height: '25px'
          //  marginLeft: '0.5rem',
        }}
      />
    </div>
  )
}


function fuzzyTextFilterFn(rows, id, filterValue) {
  return matchSorter(rows, filterValue, { keys: [row => row.values[id]] })
}

const filterTypes = {
  'select': {
    fn: SelectColumnFilter,
  },
  'multiselect': {
    fn: MultiSelectColumnFilter,
    type: multiSelectFilterFn
  },
  'switch': {
    fn: BooleanColumnFilter
  },
  'slider': {
    fn: SliderColumnFilter
  },
  'date': {
    fn: CalendarColumnFilter,
    type: dateFilterFn
  },
  'fromdatetime': {
    fn: DateTimeColumnFilter,
    type: fromDatetimeFilterFn
  },
  'todatetime': {
    fn: DateTimeColumnFilter,
    type: toDatetimeFilterFn
  },
  'range': {
    fn: RangeColumnFilter,
    type: 'between'
  },
  'minMax': {
    fn: NumberRangeColumnFilter,
    type: 'between'
  }
};
// Let the table remove the filter if the string is empty
fuzzyTextFilterFn.autoRemove = val => !val

const IndeterminateCheckbox = React.forwardRef(
  ({ indeterminate, ...rest }, ref) => {
    const defaultRef = React.useRef()
    const resolvedRef = ref || defaultRef
    React.useEffect(() => {
      resolvedRef.current.indeterminate = indeterminate
    }, [resolvedRef, indeterminate])
    return <input type="checkbox" ref={resolvedRef} {...rest} />
  }
)

// Our table component
function Table({ columns, data, defaultheader, optionalheader, tablename, defaultSortColumn, defaultpagesize, columnOrders, showAction }) {

  const filterTypes = React.useMemo(
    () => ({
      // Add a new fuzzyTextFilterFn filter type.
      fuzzyText: fuzzyTextFilterFn,
      // Or, override the default text filter to use
      // "startWith"
      text: (rows, id, filterValue) => {
        return rows.filter(row => {
          const rowValue = row.values[id]
          return rowValue !== undefined
            ? String(rowValue)
              .toLowerCase()
              .startsWith(String(filterValue).toLowerCase())
            : true
        })
      },
    }),
    []
  )

  const defaultColumn = React.useMemo(
    () => ({
      // Let's set up our default Filter UI
      Filter: DefaultColumnFilter,

    }),
    []
  )

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    setAllFilters,
    allColumns,
    getToggleHideAllColumnsProps,
    visibleColumns,
    state,
    page,
    preGlobalFilteredRows,
    setGlobalFilter,
    setHiddenColumns,
    gotoPage,
    setPageSize,
    selectedFlatRows,
    setColumnOrder,
    exportData,
  } = useTable(
    {
      columns,
      data,
      defaultColumn,
      filterTypes,
      initialState: {
        pageIndex: 0,
        pageSize: (defaultpagesize && defaultpagesize > 0) ? defaultpagesize : 10,
        sortBy: defaultSortColumn
      },
      getExportFileBlob,
    },
    useFilters,
    useGlobalFilter,
    useSortBy,
    usePagination,
    useRowSelect,
    useColumnOrder,
    useExportData
  );
  React.useEffect(() => {
    setHiddenColumns(
    //  columns.filter(column => !column.isVisible).map(column => column.accessor)
    columns.filter(column => !column.isVisible).map(column => column.id)
    );
    // console.log('columns List', visibleColumns.map((d) => d.id));
    if (columnOrders && columnOrders.length) {
      if (showAction === 'true') {
        setColumnOrder(['Select', 'Action', ...columnOrders]);
      } else {
        setColumnOrder(['Select', ...columnOrders]);
      }
    }
    
  }, [setHiddenColumns, columns]);

  let op = useRef(null);

  const [currentpage, setcurrentPage] = React.useState(0);
  const [currentrows, setcurrentRows] = React.useState(defaultpagesize);
  const [custompagevalue, setcustompagevalue] = React.useState();

  const onPagination = (e) => {
    gotoPage(e.page);
    setcurrentPage(e.first);
    setcurrentRows(e.rows);
    setPageSize(e.rows)
    if ([10, 25, 50, 100].includes(e.rows)) {
      setcustompagevalue();
    }
  };
  const onCustomPage = (e) => {
    if (typeof custompagevalue === 'undefined' || custompagevalue == null) return;
    gotoPage(0);
    setcurrentPage(0);
    setcurrentRows(custompagevalue);
    setPageSize(custompagevalue)
  };

  const onChangeCustompagevalue = (e) => {
    setcustompagevalue(e.target.value);
  }

  const onShowAllPage = (e) => {
    gotoPage(e.page);
    setcurrentPage(e.first);
    setcurrentRows(e.rows);
    setPageSize(tbldata.length)
    setcustompagevalue();
  };

  const onToggleChange = (e) => {
    let lsToggleColumns = [];
    allColumns.forEach(acolumn => {
      let jsonobj = {};
      let visible = (acolumn.Header === e.target.id) ? ((acolumn.isVisible) ? false : true) : acolumn.isVisible
      jsonobj['Header'] = acolumn.Header;
      jsonobj['isVisible'] = visible;
      lsToggleColumns.push(jsonobj)
    })
    localStorage.setItem(tablename, JSON.stringify(lsToggleColumns))
  }

  filteredData = _.map(rows, 'values');
  if (parentCallbackFunction) {
    parentCallbackFunction(filteredData);
  }

  /* Select only rows than can be selected. This is required when ALL is selected */
  selectedRows = _.filter(selectedFlatRows, selectedRow => { return (selectedRow.original.canSelect === undefined || selectedRow.original.canSelect) });
  /* Take only the original values passed to the component */
  selectedRows = _.map(selectedRows, 'original');
  /* Callback the parent function if available to pass the selected records on selection */
  if (parentCBonSelection) {
    parentCBonSelection(selectedRows)
  }

  return (
    <>
      <div style={{ display: 'flex', justifyContent: 'space-between' }}>
        <div id="block_container" >
          {allowColumnSelection &&
            <div style={{ textAlign: 'left', marginRight: '30px' }}>
              <i className="fa fa-columns col-filter-btn" label="Toggle Columns" onClick={(e) => op.current.toggle(e)} />
              {showColumnFilter &&
                <div style={{ position: "relative", top: "-25px", marginLeft: "50px", color: "#005b9f" }} onClick={() => setAllFilters([])} >
                  <i class="fas fa-sync-alt" title="Clear All Filters"></i></div>}
              <OverlayPanel ref={op} id="overlay_panel" showCloseIcon={false} >
                <div>
                  <div style={{ textAlign: 'center' }}>
                    <label>Select column(s) to view</label>
                  </div>
                  <div style={{ float: 'left', backgroundColor: '#d1cdd936', width: '250px', height: '400px', overflow: 'auto', marginBottom: '10px', padding: '5px' }}>
                    <div id="tagleid"  >
                      <div >
                        <div style={{ marginBottom: '5px' }}>
                          <IndeterminateCheckbox {...getToggleHideAllColumnsProps()} /> Select All
                            </div>
                        {allColumns.map(column => (
                          <div key={column.id} style={{ 'display': column.id !== 'actionpath' ? 'block' : 'none' }}>
                            <input type="checkbox" {...column.getToggleHiddenProps()}
                              id={(defaultheader[column.id]) ? defaultheader[column.id] : (optionalheader[column.id] ? optionalheader[column.id] : column.id)}
                              onClick={onToggleChange}
                            /> {
                              (defaultheader[column.id]) ? defaultheader[column.id] : (optionalheader[column.id] ? optionalheader[column.id] : column.id)}
                          </div>
                        ))}
                        <br />
                      </div>
                    </div>
                  </div>
                </div>
              </OverlayPanel>
            </div>
          }
          <div style={{ textAlign: 'right' }}>
            {tbldata.length > 0 && !isunittest && showGlobalFilter &&
              <GlobalFilter
                preGlobalFilteredRows={preGlobalFilteredRows}
                globalFilter={state.globalFilter}
                setGlobalFilter={setGlobalFilter}
              />
            }
          </div>


          {showTopTotal && filteredData.length === data.length &&
            <div className="total_records_top_label"> <label >Total records ({data.length})</label></div>
          }

          {showTopTotal && filteredData.length < data.length &&
            <div className="total_records_top_label" ><label >Filtered {filteredData.length} from {data.length}</label></div>}

        </div>
        {showCSV &&
          <div className="total_records_top_label" style={{ marginTop: '20px' }} >
            <a href="#" onClick={() => { exportData("csv", false); }} title="Download CSV" style={{ verticalAlign: 'middle' }}>
              <i class="fas fa-file-csv" style={{ color: 'green', fontSize: '20px' }} ></i>
            </a>
          </div>
          /* 
            <div className="total_records_top_label" >
              <a href="#"  onClick={() => {exportData("pdf", false);}} title="Download PDF" style={{verticalAlign: 'middle'}}>
                  <i class="fas fa-file-pdf" style={{color: 'red', fontSize: '20px'}}></i>
              </a>
            </div> */
        }
      </div>


      <div className="tmss-table table_container">
        <table {...getTableProps()} data-testid="viewtable" className="viewtable" >
          <thead>
            {headerGroups.map(headerGroup => (
              <tr {...headerGroup.getHeaderGroupProps()}>
                {headerGroup.headers.map(column => (
                  <th>
                    <div {...column.getHeaderProps(column.getSortByToggleProps())}>
                      {column.Header !== 'actionpath' && column.render('Header')}
                      {column.Header !== 'Action' ?
                        column.isSorted ? (column.isSortedDesc ? <i className="pi pi-sort-down" aria-hidden="true"></i> : <i className="pi pi-sort-up" aria-hidden="true"></i>) : ""
                        : ""
                      }
                    </div>

                    {/* Render the columns filter UI */}
                    {column.Header !== 'actionpath' &&
                      <div className={columnclassname[0][column.Header]}  >
                        {column.canFilter && column.Header !== 'Action' ? column.render('Filter') : null}

                      </div>
                    }
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody {...getTableBodyProps()}>
            {page.map((row, i) => {
              prepareRow(row)
              return (
                <tr {...row.getRowProps()}>
                  {row.cells.map(cell => {
                    if (cell.column.id !== 'actionpath') {
                      return <td {...cell.getCellProps()}>
                        {(cell.row.original.links || []).includes(cell.column.id) ? <Link to={cell.row.original.linksURL[cell.column.id]}>{cell.render('Cell')}</Link> : cell.render('Cell')}
                      </td>
                    }
                    else {
                      return "";
                    }
                  }
                  )}
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      <div className="pagination p-grid" >
        {filteredData.length === data.length &&
          <div className="total_records_bottom_label" ><label >Total records ({data.length})</label></div>
        }
        {filteredData.length < data.length &&
          <div className="total_records_bottom_label" ><label >Filtered {filteredData.length} from {data.length}</label></div>
        }
        <div>
          <Paginator rowsPerPageOptions={[10, 25, 50, 100]} first={currentpage} rows={currentrows} totalRecords={rows.length} onPageChange={onPagination}></Paginator>
        </div>
        <div>
          <InputNumber id="custompage" value={custompagevalue} onChange={onChangeCustompagevalue}
            min={0} style={{ width: '100px' }} />
          <label >Records/Page</label>
          <Button onClick={onCustomPage}> Show </Button>
          <Button onClick={onShowAllPage} style={{ marginLeft: "1em" }}> Show All </Button>
        </div>
      </div>
    </>
  )
}


// Define a custom filter filter function!
function filterGreaterThan(rows, id, filterValue) {
  return rows.filter(row => {
    const rowValue = row.values[id]
    return rowValue >= filterValue
  })
}

// This is an autoRemove method on the filter function that
// when given the new filter value and returns true, the filter
// will be automatically removed. Normally this is just an undefined
// check, but here, we want to remove the filter if it's not a number
filterGreaterThan.autoRemove = val => typeof val !== 'number'

function ViewTable(props) {
  const history = useHistory();
  // Data to show in table
  tbldata = props.data;
  showCSV = (props.showCSV) ? props.showCSV : false;

  parentCallbackFunction = props.filterCallback;
  parentCBonSelection = props.onRowSelection;
  isunittest = props.unittest;
  columnclassname = props.columnclassname;
  showTopTotal = props.showTopTotal === undefined ? true : props.showTopTotal;
  showGlobalFilter = props.showGlobalFilter === undefined ? true : props.showGlobalFilter;
  showColumnFilter = props.showColumnFilter === undefined ? true : props.showColumnFilter;
  allowColumnSelection = props.allowColumnSelection === undefined ? true : props.allowColumnSelection;
  allowRowSelection = props.allowRowSelection === undefined ? false : props.allowRowSelection;
  // Default Header to show in table and other columns header will not show until user action on UI
  let defaultheader = props.defaultcolumns;
  let optionalheader = props.optionalcolumns;
  let defaultSortColumn = props.defaultSortColumn;
  let tablename = (props.tablename) ? props.tablename : window.location.pathname;

  if (!defaultSortColumn) {
    defaultSortColumn = [{}];
  }
  let defaultpagesize = (typeof props.defaultpagesize === 'undefined' || props.defaultpagesize == null) ? 10 : props.defaultpagesize;
  let columns = [];
  let defaultdataheader = Object.keys(defaultheader[0]);
  let optionaldataheader = Object.keys(optionalheader[0]);

  /* If allowRowSelection property is true for the component, add checkbox column as 1st column.
     If the record has property to select, enable the checkbox */
  if (allowRowSelection) {
    columns.push({
      Header: ({ getToggleAllRowsSelectedProps }) => {
        return (
          <div>
            <IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} style={{ width: '15px', height: '15px' }} />
          </div>
        )
      },
      id: 'Select',
      accessor: props.keyaccessor,
      Cell: ({ row }) => {
        return (
          <div>
            {(row.original.canSelect === undefined || row.original.canSelect) &&
              <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} style={{ width: '15px', height: '15px' }} />
            }
            {row.original.canSelect === false &&
              <input type="checkbox" checked={false} disabled style={{ width: '15px', height: '15px' }}></input>
            }
          </div>
        )
      },
      disableFilters: true,
      disableSortBy: true,
      isVisible: defaultdataheader.includes(props.keyaccessor),
    });
  }

  if (props.showaction === 'true') {
    columns.push({
      Header: 'Action',
      id: 'Action',
      accessor: props.keyaccessor,
      Cell: props => <button className='p-link' onClick={navigateTo(props)} ><i className="fa fa-eye" style={{ cursor: 'pointer' }}></i></button>,
      disableFilters: true,
      disableSortBy: true,
      isVisible: defaultdataheader.includes(props.keyaccessor),
    })
  }

  const navigateTo = (props) => () => {
    if (props.cell.row.values['actionpath']) {
      return history.push({
        pathname: props.cell.row.values['actionpath'],
        state: {
          "id": props.value,
        }
      })
    }
    // Object.entries(props.paths[0]).map(([key,value]) =>{})
  }

  //Default Columns
  defaultdataheader.forEach(header => {
    const isString = typeof defaultheader[0][header] === 'string';
    const filterFn = (showColumnFilter ? (isString ? DefaultColumnFilter : (filterTypes[defaultheader[0][header].filter] && filterTypes[defaultheader[0][header].filter].fn ? filterTypes[defaultheader[0][header].filter].fn : DefaultColumnFilter)) : "");
    const filtertype = (showColumnFilter ? (!isString && filterTypes[defaultheader[0][header].filter] && filterTypes[defaultheader[0][header].filter].type) ? filterTypes[defaultheader[0][header].filter].type : 'fuzzyText' : "");
    columns.push({
      Header: isString ? defaultheader[0][header] : defaultheader[0][header].name,
      id: isString ? defaultheader[0][header] : defaultheader[0][header].name,
      accessor: header,
      filter: filtertype,
      Filter: filterFn,
      //*** TO REMOVE - INCOMING CHANGE */
      // filter: (showColumnFilter?((!isString && defaultheader[0][header].filter=== 'date') ? 'includes' : 'fuzzyText'):""),
      // Filter: (showColumnFilter?(isString ? DefaultColumnFilter : (filterTypes[defaultheader[0][header].filter] ? filterTypes[defaultheader[0][header].filter] : DefaultColumnFilter)):""),
      isVisible: true,
      Cell: props => <div> {updatedCellvalue(header, props.value, defaultheader[0][header])} </div>,
    })
  })

  //Optional Columns
  optionaldataheader.forEach(header => {
    const isString = typeof optionalheader[0][header] === 'string';
    const filterFn = (showColumnFilter ? (isString ? DefaultColumnFilter : (filterTypes[optionalheader[0][header].filter] && filterTypes[optionalheader[0][header].filter].fn ? filterTypes[optionalheader[0][header].filter].fn : DefaultColumnFilter)) : "");
    const filtertype = (showColumnFilter ? (!isString && filterTypes[optionalheader[0][header].filter]) ? (filterTypes[optionalheader[0][header].filter].type || filterTypes[optionalheader[0][header].filter]) : 'fuzzyText' : "");
    columns.push({
      Header: isString ? optionalheader[0][header] : optionalheader[0][header].name,
      id: isString ? header : optionalheader[0][header].name,
      accessor: header,
      filter: filtertype,
      Filter: filterFn,
      isVisible: false,
      Cell: props => <div> {updatedCellvalue(header, props.value, optionalheader[0][header])} </div>,
    })
  });

  let togglecolumns = localStorage.getItem(tablename);
  if (togglecolumns) {
    togglecolumns = JSON.parse(togglecolumns)
    columns.forEach(column => {
      togglecolumns.filter(tcol => {
        column.isVisible = (tcol.Header === column.Header) ? tcol.isVisible : column.isVisible;
        return tcol;
      })
    })
  }

  function updatedCellvalue(key, value, properties) {
    try {
      if (key === 'blueprint_draft' && _.includes(value, '/task_draft/')) {
        //  'task_draft/' -> len = 12
        var taskid = _.replace(value.substring((value.indexOf('/task_draft/') + 12), value.length), '/', '');
        return <a href={'/task/view/draft/' + taskid}>{' ' + taskid + ' '}</a>
      } else if (key === 'blueprint_draft') {
        var retval = [];
        value.forEach((link, index) => {
          //  'task_blueprint/' -> len = 16
          if (_.includes(link, '/task_blueprint/')) {
            var bpid = _.replace(link.substring((link.indexOf('/task_blueprint/') + 16), link.length), '/', '');
            retval.push(<a href={'/task/view/blueprint/' + bpid} key={bpid + index} >{'  ' + bpid + '  '}</a>)
          }
        })
        return retval;
      } else if (typeof value == "boolean") {
        return value.toString();
      }else if (typeof value == "string") {
        const format = properties ? properties.format : 'YYYY-MM-DD HH:mm:ss';
        const dateval = moment(value, moment.ISO_8601).format(format);
        if (dateval !== 'Invalid date') {
          return dateval;
        }
     }
    } catch (err) {
      console.error('Error', err)
    }
    return value;
  }

  return (
    <div>
      <Table columns={columns} data={tbldata} defaultheader={defaultheader[0]} optionalheader={optionalheader[0]} showAction={props.showaction}
        defaultSortColumn={defaultSortColumn} tablename={tablename} defaultpagesize={defaultpagesize} columnOrders={props.columnOrders} />
    </div>
  )
}

export default ViewTable