import { bind } from 'decko';
import { Component, h } from 'preact';
import { Xterm, XtermOptions } from './xterm';

import '@xterm/xterm/css/xterm.css';
import { Modal } from '../modal';

interface Props extends XtermOptions {
    id: string;
}

interface State {
    modal: boolean;
}

export class Terminal extends Component<Props, State> {
    private container: HTMLElement;
    private xterm: Xterm;
    private intervalID: NodeJS.Timeout;
    private currentDevcontainer = {
        title: 'Devcontainer Info',
        detail: 'No Devcontainer Created yet',
        port: '',
        ip:'',
        steps: [
          // {
          //   summary: '',
          //   duration: '',
          //   status: '',
          //   logs:{
          //   },
          // }
        ],
      };
    constructor(props: Props) {
        super();
        this.xterm = new Xterm(props, this.showModal);
    }

    async componentDidMount() {
        await this.xterm.refreshToken();
        const options = new URLSearchParams(decodeURIComponent(window.location.search));
        
        const params = new URLSearchParams({
            repo: options.get('repoid') as string,
            user: options.get('userid') as string,
        });
        fetch('http://' + 
            options.get('domain') + 
            ':'+ 
            options.get('port') +
            '/' + 
            options.get('user') + 
            '/' + 
            options.get('repo') + 
            '/devcontainer/status?' + 
            params
    )
            .then(response => response.json())
            .then(data => {
                if (data.status !== '-1') {
                    if (options.get('type') === 'docker') {
                        this.xterm.open(this.container);
                        this.xterm.connect();
                    } else {
                        this.intervalID = setInterval(this.loadOutput, 8000);
                        this.xterm.open(this.container);
                        this.xterm.changeUrl(this.currentDevcontainer.ip, this.currentDevcontainer.port)
                        this.xterm.changeStatus(true);
                        this.xterm.connect();
                    }
                }
            })
            .catch(error => {
                console.error('Error:', error);
            });

    }

    componentWillUnmount() {
        this.xterm.dispose();
    }

    render({ id }: Props, { modal }: State) {
        return (
            <div id={id} ref={c => (this.container = c as HTMLElement)}>
                <Modal show={modal}>
                    <label class="file-label">
                        <input onChange={this.sendFile} class="file-input" type="file" multiple />
                        <span class="file-cta">Choose files…</span>
                    </label>
                </Modal>
            </div>
        );
    }

    @bind
    showModal() {
        this.setState({ modal: true });
    }

    @bind
    sendFile(event: Event) {
        this.setState({ modal: false });
        const files = (event.target as HTMLInputElement).files;
        if (files) this.xterm.sendFile(files);
    }

    @bind
    private loadOutput() {
        const options = new URLSearchParams(decodeURIComponent(window.location.search));
        const params = new URLSearchParams({
            repo: options.get('repoid') as string,
            user: options.get('userid') as string,
        });
        
        fetch(
            'http://' + options.get('domain') + ':'+ options.get('port') +'/' +
                options.get('user') +
                '/' +
                options.get('repo') +
                '/devcontainer/output?' +
                params
        )
            .then(response => response.json())
            .then(job => {
                if (!job) {
                    clearInterval(this.intervalID);
                    this.intervalID = null as any;
                    return;
                }
                if(this.currentDevcontainer.steps.length < job.currentDevcontainer.steps.length){
                    for(let i = this.currentDevcontainer.steps.length; i < job.currentDevcontainer.steps.length; i++) {
                        this.xterm.writeData(job.currentDevcontainer.steps[i].summary);
                        this.xterm.writeData('\r\n');
                        for(let j = 0; j < job.currentDevcontainer.steps[i].logs.length; j++) {
                            this.xterm.writeData(job.currentDevcontainer.steps[i].logs[j].message.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n'));
                            this.xterm.writeData('\r\n');
                        }
                    }
                }
                this.currentDevcontainer = job.currentDevcontainer;
                if (this.currentDevcontainer.detail === '4' && this.intervalID) {
                    clearInterval(this.intervalID);
                    this.intervalID = null as any;
                }
            })
            .catch(error => {
                console.error('Error:', error);
            });
    }
}
