import { GetControlplaneEndpoint } from 'dashboard/core/utils/env';
import { ResourceLoadStatus } from 'dashboard/definitions/resources';
import { code } from 'dashboard/generated/controlplane';
import { createAuditLogs } from 'dashboard/generated/controlplane/twirp';
import * as _ from 'lodash';
import * as React from 'react';
import { Display, Layout } from 'twitch-core-ui';
import { AuditLogsTable } from './baseComponent';
import { AuditLogDetailsModal } from './detailsModal';
import { Filter } from './filter';
import { AuditLogTitle } from './title';
import { filter, filterableFields } from './util';

import twirp = code.justin.tv.eventbus.controlplane;

interface Props {
  service: twirp.IService;
}

interface State {
  auditLogs: twirp.AuditLog[];
  activeFilters: filter[];
  loading: ResourceLoadStatus;
  selectedAuditLog: number | null;
}

export class AuditLogsTableWrapper extends React.PureComponent<Props, State> {
  public state: State = {
    auditLogs: new Array<twirp.AuditLog>(0),
    activeFilters: [],
    loading: ResourceLoadStatus.LOADING,
    selectedAuditLog: null,
  };
  private auditLogsClient: twirp.AuditLogs;

  constructor(props: Props) {
    super(props);

    this.auditLogsClient = createAuditLogs(GetControlplaneEndpoint());
  }

  public componentDidMount() {
    this.fetchAuditLogs();
  }

  public render() {
    return (
      <div className="auditLogTable">
        <Layout>
          <AuditLogTitle />
          <Layout display={Display.Flex} padding={{ y: 1 }}>
            {_.map(filterableFields, (field) => {
              return (
                <Filter
                  field={field}
                  key={field}
                  auditLogs={this.state.auditLogs}
                  addActiveFilter={this.addActiveFilter}
                  removeActiveFilter={this.removeActiveFilter}
                />
              );
            })}
          </Layout>
          {this.state.selectedAuditLog !== null && (
            <AuditLogDetailsModal
              close={this.closeDetailsModal}
              auditLog={this.state.auditLogs[this.state.selectedAuditLog]}
            />
          )}
          <AuditLogsTable
            auditLogs={this.state.auditLogs}
            loading={this.state.loading}
            filters={this.state.activeFilters}
            openDetailsModal={this.openDetailsModal}
          />
        </Layout>
      </div>
    );
  }

  private fetchAuditLogs = async () => {
    this.setState({
      loading: ResourceLoadStatus.LOADING,
    });

    const req = new twirp.GetAuditLogsForServiceReq({
      serviceId: this.props.service.id,
    });

    try {
      const auditLogs = await this.auditLogsClient.getAuditLogsForService(req);
      const auditLogsResp = await auditLogs.toJSON();
      this.setState({
        auditLogs: auditLogsResp.auditLogs,
        loading: ResourceLoadStatus.COMPLETED,
      });
    } catch (err) {
      this.setState({
        loading: ResourceLoadStatus.ERRORED,
      });
    }
  }

  private addActiveFilter = (f: filter) => {
    const activeFilters = _.cloneDeep(this.state.activeFilters);
    activeFilters.push(f);
    this.setState({ activeFilters });
  }

  private removeActiveFilter = (targetFilter: filter) => {
    const activeFilters = _.cloneDeep(this.state.activeFilters);
    _.remove(activeFilters, (activeFilter) => {
      return _.isEqual(activeFilter, targetFilter);
    });
    this.setState({ activeFilters });
  }

  private closeDetailsModal = () => {
    const selectedAuditLog = null;
    this.setState({ selectedAuditLog });
  }

  private openDetailsModal = (i: number) => {
    const selectedAuditLog = i;
    this.setState({ selectedAuditLog });
  }
}
