import Script from "../Script"
import fs from "fs"
import { Feature, FeatureCollection } from "geojson"
import { GeoOperations } from "../../src/Logic/GeoOperations"

// vite-node scripts/velopark/compare.ts -- velopark_all.geojson osm_with_velopark_link_.geojson
class Compare extends Script {
    compare(
        veloId: string,
        osmParking: Feature,
        veloParking: Feature
    ): {
        distance: number
        ref: string
        osmid: string
        diffs: {
            osm: string
            velopark: string
            key: string
        }[]
    } {
        const osmCenterpoint = GeoOperations.centerpointCoordinates(osmParking)
        const veloparkCenterpoint = GeoOperations.centerpointCoordinates(veloParking)
        const distance = Math.round(
            GeoOperations.distanceBetween(osmCenterpoint, veloparkCenterpoint)
        )
        const diffs: { osm: string; velopark: string; key: string }[] = []

        const allKeys = new Set<string>(
            Object.keys(osmParking.properties).concat(Object.keys(veloParking.properties))
        )
        for (const key of allKeys) {
            if (["name", "numberOfLevels", "id"].indexOf(key) >= 0) {
                continue // We don't care about these tags
            }
            if (osmParking.properties[key] === veloParking.properties[key]) {
                continue
            }
            if (Number(osmParking.properties[key]) === veloParking.properties[key]) {
                continue
            }
            if (veloParking.properties[key] === undefined) {
                continue
            }
            diffs.push({
                key,
                osm: osmParking.properties[key],
                velopark: veloParking.properties[key],
            })
        }
        let osmid =
            osmParking.properties["@id"] ??
            osmParking["id"] /*Not in the properties, that is how overpass returns it*/
        if (!osmid.startsWith("http")) {
            osmid = "https://openstreetmap.org/" + osmid
        }

        return {
            ref: veloId,
            osmid,
            distance,
            diffs,
        }
    }

    async main(args: string[]): Promise<void> {
        let [velopark, osm, key] = args
        if (velopark === undefined || osm === undefined) {
            console.log(
                "Needed argument: velopark.geojson osm.geojson [key]\nThe key is optional and will be `ref:velopark` by default\nUse overpass to get a geojson with ref:velopark"
            )
            return
        }
        key ??= "ref:velopark"
        const veloparkData: FeatureCollection = JSON.parse(fs.readFileSync(velopark, "utf-8"))
        const osmData: FeatureCollection = JSON.parse(fs.readFileSync(osm, "utf-8"))

        const veloparkById: Record<string, Feature> = {}
        for (const parking of veloparkData.features) {
            veloparkById[parking.properties[key] ?? parking.properties.url] = parking
        }

        const diffs = []
        for (const parking of osmData.features) {
            const veloId = parking.properties[key]
            const veloparking = veloparkById[veloId]
            if (veloparking === undefined) {
                console.error("No velopark entry found for", veloId)
                continue
            }
            console.log("Veloparking is", veloparking)
            diffs.push(this.compare(veloId, parking, veloparking))
        }
        console.log(
            "Found ",
            diffs.length,
            " items with differences between OSM and the provided data"
        )

        const maxDistance = Math.max(...diffs.map((d) => d.distance))
        const distanceBins = []
        const binSize = 5
        for (let i = 0; i < Math.ceil(maxDistance / binSize); i++) {
            distanceBins.push(0)
        }
        for (const diff of diffs) {
            const bin = Math.floor(diff.distance / binSize)
            distanceBins[bin] += 1
        }

        fs.writeFileSync(
            "report_diff.json",
            JSON.stringify(
                {
                    diffs,
                    distanceBins,
                    binSize,
                    "#binsize": "Every bin increases with this amount in meter",
                },
                null,
                "  "
            )
        )
        console.log("Written report_diff.json")
    }

    constructor() {
        super(
            "Compares a velopark geojson with OSM geojson. Usage: `compare velopark.geojson osm.geojson [key-to-compare-on]`. If key-to-compare-on is not given, `ref:velopark` will be used"
        )
    }
}

new Compare().run()
