import { InputType } from "./parser.ts";
import { parseInput, MapType } from "./parser.ts";

type Range = {
    start: number, // inclusive
    length: number, // exclusive
}

function getIntersection(r1: Range, r2: Range): Range | null {
    if (r1.start + r1.length <= r2.start) {
        return null;
    }
    if (r2.start + r2.length <= r1.start) {
        return null;
    }
    return {
        start: Math.max(r1.start, r2.start),
        length: Math.min(r1.start + r1.length, r2.start + r2.length) - Math.max(r1.start, r2.start)
    };
}

function mappingRange(m: MapType, input: Range): Range[] {
    const result: Range[] = []; 

    //collect all unmapped range
    const unmappedRange: Range[] = [];
    let curPos = 0;
    for (let i = 0; i < m.data.length; i++) {
        // data is sorted by src
        const d = m.data[i];
        if (curPos < d.src) {
            unmappedRange.push({
                start: curPos,
                length: d.src - curPos
            });
        }
        curPos = d.src + d.range;
    }
    unmappedRange.push({
        start: curPos,
        length: Infinity
    });

    // collect all intersecting range
    for (let i = 0; i < m.data.length; i++) {
        const d = m.data[i];
        const intersection = getIntersection(input, {
            start: d.src,
            length: d.range
        })
        if (intersection === null) {
            continue;
        }
        // mapping
        result.push({
            start: d.dst + intersection.start - d.src,
            length: intersection.length
        });
    }

    // add unmapped range
    for (let i = 0; i < unmappedRange.length; i++) {
        const intersection = getIntersection(input, unmappedRange[i]);
        if (intersection === null) {
            continue;
        }
        result.push(intersection);
    }
    // console.log("mapType", m)
    // console.log("input", input)
    // console.log("unmapped", unmappedRange)
    // console.log("result",result)

    return result;
}

const input = await Deno.readTextFile("input.txt");
const r = parseInput(input);

function composition(r: InputType, input: Range) {
    let result = [input];
    for (let i = 0; i < r.map.length; i++) {
        const m = r.map[i];
        result = result.flatMap(r => mappingRange(m, r));
    }
    return result

    // ["soil", "fertilizer", "water", "light", "temperature", "humidity", "location"].forEach((key) => {
    //     const m = r.map.filter(m => m.to === key)[0];
    
    // });
}

let min = Infinity;
for (let i = 0; i < r.seeds.length; i += 2) {
    const seed = r.seeds[i];
    const seedLength = r.seeds[i + 1];
    const seedRange = { start: seed, length: seedLength };
    const location = composition(r, seedRange);
    console.log("location", location);
    const minStart = location.reduce((a, b) => Math.min(a, b.start), Infinity);
    min = Math.min(min, minStart);
}
console.log(min);
