// The transport strip: sections coloured by kind, bar ticks, scene-change
// markers, playhead.
//
// This is the review surface. Segmentation problems are visible here at a glance
// in a way they are not from watching the video — a boundary in the wrong place
// shows up as a coloured block that doesn't line up with what you're hearing.

const KIND_COLORS = {
    intro:     '#2f4858',
    build:     '#8a5a2b',
    drop:      '#b5323c',
    sustain:   '#3a6b52',
    breakdown: '#3d3a6b',
    outro:     '#43404a',
};

export class TimelineStrip {
    constructor(canvas, { onSeek = null } = {}) {
        this.canvas = canvas;
        this.ctx = canvas.getContext('2d');
        this.onSeek = onSeek;
        this.show = null;
        this.frame = 0;
        this.hoverFrame = -1;
        this.loopSection = -1;

        canvas.addEventListener('pointerdown', (e) => this._seekFromEvent(e));
        canvas.addEventListener('pointermove', (e) => {
            const rect = canvas.getBoundingClientRect();
            this.hoverFrame = this._frameAt(e.clientX - rect.left, rect.width);
            if (e.buttons & 1) this._seekFromEvent(e);
        });
        canvas.addEventListener('pointerleave', () => { this.hoverFrame = -1; });
    }

    setShow(show) { this.show = show; }
    setFrame(frame) { this.frame = frame; }
    setLoopSection(index) { this.loopSection = index; }

    _frameAt(x, width) {
        if (!this.show || !this.show.ready) return 0;
        return Math.round((x / Math.max(1, width)) * (this.show.frameCount - 1));
    }

    _seekFromEvent(event) {
        if (!this.onSeek || !this.show || !this.show.ready) return;
        const rect = this.canvas.getBoundingClientRect();
        this.onSeek(this._frameAt(event.clientX - rect.left, rect.width));
    }

    resize() {
        const rect = this.canvas.getBoundingClientRect();
        const dpr = window.devicePixelRatio || 1;
        this.canvas.width = Math.max(1, Math.round(rect.width * dpr));
        this.canvas.height = Math.max(1, Math.round(rect.height * dpr));
        this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
        this._w = rect.width;
        this._h = rect.height;
    }

    draw() {
        const ctx = this.ctx;
        const w = this._w || this.canvas.width;
        const h = this._h || this.canvas.height;
        ctx.clearRect(0, 0, w, h);

        ctx.fillStyle = '#0e1016';
        ctx.fillRect(0, 0, w, h);

        const show = this.show;
        if (!show || !show.ready) return;

        const track = show.track;
        const total = show.frameCount;
        const toX = (frame) => (frame / total) * w;

        // Sections.
        for (const section of track.sections) {
            const x0 = toX(section.startFrame);
            const x1 = toX(section.endFrame);
            const look = show.look.sections[section.index];

            ctx.fillStyle = KIND_COLORS[section.kind] || '#333';
            ctx.fillRect(x0, 0, Math.max(1, x1 - x0), h);

            if (look && look.locked) {
                ctx.save();
                ctx.strokeStyle = 'rgba(250, 204, 21, 0.85)';
                ctx.lineWidth = 2;
                ctx.strokeRect(x0 + 1, 1, Math.max(1, x1 - x0) - 2, h - 2);
                ctx.restore();
            }
            if (section.index === this.loopSection) {
                ctx.fillStyle = 'rgba(255,255,255,0.10)';
                ctx.fillRect(x0, 0, Math.max(1, x1 - x0), h);
            }

            ctx.save();
            ctx.beginPath();
            ctx.rect(x0, 0, Math.max(0, x1 - x0), h);
            ctx.clip();
            ctx.fillStyle = 'rgba(255,255,255,0.72)';
            ctx.font = '10px ui-monospace, monospace';
            ctx.fillText(section.kind, x0 + 5, 13);
            if (look) {
                ctx.fillStyle = 'rgba(255,255,255,0.45)';
                ctx.fillText(look.layers[0].module.name, x0 + 5, h - 6);
            }
            ctx.restore();

            // Boundary line.
            ctx.strokeStyle = 'rgba(0,0,0,0.65)';
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.moveTo(x0 + 0.5, 0);
            ctx.lineTo(x0 + 0.5, h);
            ctx.stroke();
        }

        // Bar ticks — sparse enough to stay readable on a long track.
        const barSeconds = (track.tempo.period * track.tempo.beatsPerBar) / track.fps;
        const pixelsPerBar = (barSeconds * track.fps / total) * w;
        if (pixelsPerBar > 6) {
            const every = pixelsPerBar > 18 ? 1 : 4;
            ctx.strokeStyle = 'rgba(255,255,255,0.10)';
            ctx.beginPath();
            let bar = 0;
            for (let t = 0; t < track.duration; t += barSeconds, bar++) {
                if (bar % every) continue;
                const x = Math.round(toX(t * track.fps)) + 0.5;
                ctx.moveTo(x, h - 7);
                ctx.lineTo(x, h);
            }
            ctx.stroke();
        }

        // Hover.
        if (this.hoverFrame >= 0) {
            ctx.fillStyle = 'rgba(255,255,255,0.16)';
            ctx.fillRect(toX(this.hoverFrame), 0, 1, h);
        }

        // Playhead.
        const px = toX(this.frame);
        ctx.fillStyle = '#f8fafc';
        ctx.fillRect(px - 1, 0, 2, h);
        ctx.fillStyle = 'rgba(248,250,252,0.25)';
        ctx.fillRect(0, h - 2, px, 2);
    }
}

export { KIND_COLORS };
