import React from 'react';
import { Link, useParams } from 'react-router-dom';
import { S3Client, ListObjectsV2Command, HeadObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';

import Button from 'react-bootstrap/Button';
import ListGroup from 'react-bootstrap/ListGroup';
import Modal from 'react-bootstrap/Modal';
import Stack from 'react-bootstrap/Stack';

import { BsFileEarmarkText, BsDownload, BsHourglassSplit, BsCheckCircle } from 'react-icons/bs';
import { AiOutlineDelete } from 'react-icons/ai';

import downloadFile from './downloadFile';
import fileSizePretty from './fileSizePretty';

interface Props {
  client: S3Client;
  bucket: string;
  prefix: string;
  onUploadComplete: () => void;
}

type State = {
  iFile: number;
  show: boolean;
  files: File[];
  processing: boolean;
  canceled: boolean;
  progressEach: number[];
};

class UploadFiles extends React.Component<Props, State> {
  file_input: HTMLInputElement | null = null;

  state = {
    iFile: 0,
    show: true,
    files: [],
    processing: false,
    canceled: false,
    progressEach: [],
  };

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

  async componentDidMount() {
    this.addFile();
  }
  
  handleClose() {
    this.setState({show: false});
  }

  handleFileChange() {
    let infiles = this.file_input!.files || [];
    let files: File[] = this.state.files;

    for (var i = 0; i < infiles.length; i++) {
      files.push(infiles[i]);
    }

    this.setState({show: (files.length > 0), files: files, iFile: this.state.iFile + 1});
  }

  addFile() {
    this.file_input!.click();
  }

  removeFile(i: number) {
    let files: File[] = this.state.files;
    files.splice(i, 1);
    this.setState({files: files});
  }

  async processUpload() {
    this.setState({canceled: false});

    let progressEach: number[] = [];
    for (var i = 0; i < this.state.files.length; i++) {
      progressEach.push(0);
    }
    this.setState({canceled: false, processing: true, progressEach: progressEach});

    for (var i = 0; i < this.state.files.length; i++) {
      let file: File = this.state.files[i];
      let req = new PutObjectCommand({
        Bucket: this.props.bucket,
        Key: this.props.prefix + file.name,
        ContentType: file.type,
        ContentLength: file.size,
        Body: file,
      });
      let resp = await this.props.client.send(req);
      progressEach[i] = 100;
      this.setState({progressEach: progressEach});
    }

    this.setState({show: false});
    this.props.onUploadComplete();
  }

  render() {
    return <>
      <Modal show={this.state.show} onHide={() => this.handleClose()}>
        <Modal.Header closeButton>
          <Modal.Title>
            Upload files
          </Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <input
            key={ "file" + this.state.iFile }
            type="file" id="file_input"
            ref={input => this.file_input = input}
            onChange={() => this.handleFileChange()}
            multiple
            hidden />
          { this.state.files.length == 0 ? <p>No files added yet, click "add file" below.</p> : <></> }
          <ListGroup>
            { this.state.files.map((f: File, i: number) =>
              <ListGroup.Item>
                <Stack direction="horizontal">
                  <div className="mt-1">
                    <BsFileEarmarkText /> { f.name }
                  </div>
                  <div className="ms-auto">
                    { this.state.processing ?
                      (this.state.progressEach[i] == 100 ?  <BsCheckCircle />
                      : this.state.progressEach[i] > 0 ? this.state.progressEach[i] + "%"
                      : <BsHourglassSplit /> )
                    :
                      <Button variant="danger" size="sm" onClick={() => this.removeFile(i)}>
                        <AiOutlineDelete />
                      </Button>
                    }
                  </div>
                </Stack>
                <Stack direction="horizontal">
                  <div className="px-2">&nbsp;</div>
                  <div className="small">
                    { fileSizePretty(f.size) } - { f.type }
                  </div>
                </Stack>
              </ListGroup.Item>
            )}
          </ListGroup>
        </Modal.Body>
        <Modal.Footer>
          <Button variant="success" onClick={() => this.addFile()}>
            Add file
          </Button>
          <Button variant="primary" onClick={() => this.processUpload()} disabled={this.state.files.length == 0}>
             Upload
          </Button>
        </Modal.Footer>
      </Modal>
    </>;
  }
};

export default UploadFiles;
