
import { TapeData } from '../types';
import Apple2IO from '../apple2io';
import { debug } from '../util';

export const TAPE_TYPES = ['wav', 'aiff', 'aif', 'mp3', 'm4a'] as const;

export default class Tape {
    constructor(private readonly io: Apple2IO) {}

    public doLoadLocalTape(file: File, done?: () => void) {
        const kHz = this.io.getKHz();

        // Audio Buffer Source
        let context: AudioContext;
        if (AudioContext) {
            context = new AudioContext();
        } else {
            window.alert('Not supported by your browser');
            done && done();
            return;
        }

        const fileReader = new FileReader();
        fileReader.onload = (ev: ProgressEvent) => {
            const target: FileReader = ev.target as FileReader;
            const result: ArrayBuffer = target.result as ArrayBuffer;
            context.decodeAudioData(result).then((buffer) => {
                const buf: TapeData = [];
                const data = buffer.getChannelData(0);
                let datum = data[0];
                let old = (datum > 0.0), current;
                let last = 0;
                let delta: number;
                debug(`Sample Count: ${data.length}`);
                debug(`Sample rate: ${buffer.sampleRate}`);
                for (let idx = 1; idx < data.length; idx++) {
                    datum = data[idx];
                    if ((datum > 0.1) || (datum < -0.1)) {
                        current = (datum > 0.0);
                        if (current !== old) {
                            delta = idx - last;
                            if (delta > 2000000) {
                                delta = 2000000;
                            }
                            let ival = delta / buffer.sampleRate * 1000;
                            if (ival >= 0.550 && ival < 0.750) {
                                ival = 0.650; // Header
                            } else if (ival >= 0.175 && ival < 0.225) {
                                ival = 0.200; // sync 1
                            } else if (ival >= 0.225 && ival < 0.275) {
                                ival = 0.250; // 0 / sync 2
                            } else if (ival >= 0.450 && ival < 0.550) {
                                ival = 0.500; // 1
                            } else {
                                // debug(idx + ' ' + buf.length + ' ' + ival);
                            }
                            buf.push([ival * kHz, current]);
                            old = current;
                            last = idx;
                        }
                    }
                }
                this.io.setTape(buf);
                if (done) {
                    done();
                }
            }, (error: Error) => {
                window.alert(error.message);
            });
        };
        fileReader.readAsArrayBuffer(file);
    }
}
