import Script from "../Script"
import { writeFileSync } from "fs"
import { Feature, Geometry } from "geojson"
import { OsmObject } from "../../src/Logic/Osm/OsmObject"
import OsmObjectDownloader from "../../src/Logic/Osm/OsmObjectDownloader"
import { Changes } from "../../src/Logic/Osm/Changes"
import { ImmutableStore } from "../../src/Logic/UIEventSource"
import { OsmConnection } from "../../src/Logic/Osm/OsmConnection"
import ChangeTagAction from "../../src/Logic/Osm/Actions/ChangeTagAction"
import { Tag } from "../../src/Logic/Tags/Tag"
import { ChangeDescription } from "../../src/Logic/Osm/Actions/ChangeDescription"
import { GeoOperations } from "../../src/Logic/GeoOperations"
import { Overpass } from "../../src/Logic/Osm/Overpass"
import { TagUtils } from "../../src/Logic/Tags/TagUtils"
import { BBox } from "../../src/Logic/BBox"

export default class CleanRepair extends Script {
    constructor() {
        super("Cleans 'repair'-tags for mass retagging")
    }

    async main(args: string[]) {
        const path = args[0]
        console.log("Loading", path)
        const criteria = TagUtils.Tag({
            and: [
                "repair~*",
                "repair!=no",
                "repair!=yes",
                "repair!=brand",
                "repair!=only",
                "repair!=only_sold",
                "repair!=assisted_self_service",
            ],
        })
        const overpass = new Overpass("https://overpass-api.de/api/interpreter", criteria)
        const data: Feature<Geometry, Record<string, string>>[] = (
            await overpass.queryGeoJson(BBox.global)
        )[0].features
        console.log("Got", data.length, "features; sample", data[0])
        const changes = new Changes({
            dryRun: new ImmutableStore(true),
            osmConnection: new OsmConnection({
                dryRun: new ImmutableStore(true),
            }),
        })

        const metakeys = ["id", "version", "changeset", "user", "uid", "timestamp"]

        const replace = {
            phone: "mobile_phone",
            phones: "mobile_phone",
            mobile: "mobile_phone",
            cellphone: "mobile_phone",
            pc: "computers",
            mobile_phones: "mobile_phone",
            mobilephones: "mobile_phone",
            mobilephone: "mobile_phone",
            clocks: "clock",
            elektronik: "electronics",
            tires: "tyres",
            welcome: "yes",
            tyre: "tyres",
            electronic_products: "electronics",
            shoe: "shoes",
            pc_repairs: "computer",
            computers: "computer",
            body_construction: "body_work",
            body: "body_work",

            body_repairer: "body_work",
            instruments: "musical_instrument",
            service: "yes",
            punture: "tyres",
            electricity: "electronics",
            self_service: "assisted_self_repair",
            paint: "bodywork",
            "paint shop": "bodywork",
            paint_shop: "bodywork",
            lawnmower: "lawn_mower",
            aircon: "air_conditioning",
            "*": "yes",
            ammeublement: "furniture",
            all: "yes",
            appliances: "appliance",
            electronic: "electronics",
            escooter: "electric_scooter",
            "aviation maintenance, repair, and_overhaul": "airplane",
            aviation_maintenance: "airplanes",
            bags: "bag",
            boats: "boat",
            boilers: "boiler",
            breaks: "brakes",
            car: "cars",
            tv: "television",
            clothing: "clothes",
            coat_of_lacquer: "body_work",
            cycle: "bicycle",
            cars: "car",
            blacharstwo: "tin",
            lakiernictwo: "body_work",
            tire: "tyres",
            powder_coating: "body_work",
            leather_products: "leather",
            motocycle: "motorcycle",
            motor: "motorcycle",
            motoo: "motorcycle",
            motorbike: "motorcycle",
            motorcycle_repair: "motorcycle",
            motorsports: "motorcycle",
            printers: "printer",
            tyres24: "tyres",
            paintings: "painting",
            paintwork: "body_work",
            pumps: "pump",
            "shoes:yes": "shoes",
            wheel: "tyres",
            wheels: "tyres",
            vacuum: "vacuum_cleaner",
            glass: "car_glassj",
        }

        const brands = [
            "garage",
            "audi",
            "renault",
            "apple",
            "honda",
            "ducati",
            "ford",
            "mazda",
            "garage_renault_aie",
        ]

        const valid = [
            "train",
            "tv",
            "jewelry",
            "scooter",
            ...Object.values(replace),
            "watch",
            "oldtimer",
            "car",
            "bicycle",
            "boat",
            "windbreaker",
            "agricultural",
            "alternator",
            "antiques",
            "atv",
            "auto",
            "aviation maintenance",
            "bag",
            "bags",
            "battery",
            "bicyle",
            "borehole",
            "building",
            "camera",
            "car_glass",
            "caravan",
            "carpenter",
            "coffee_machine",
            "construction machinery",
            "cycle",
            "dentures",
            "ducati",
            "electric motor",
            "electric_bike",
            "electric_scooter",
            "espresso_machines",
            "exhaust",
            "fire_extinguishers",
            "fountain_pen",
            "fridge",
            "garden_machinery",
            "gas appliances",
            "generator",
            "glasses",
            "golfcart",
            "guitar",
            "hammock",
            "hardware",
            "heating pumps",
            "hifi",
            "hvac",
            "installation",
            "jewellery",
            "keys",
            "kick_scooter",
            "kitesurfing",
            "tools",
            "toys",
            "tractor",
            "trailer",
            "transformer",
            "truck",
            "typewriter",
            "sail",
            "sewing_machine",
            "ship",
            "picture",
            "pillow",
            "plastic",
            "cash_register",
            "cnc",
            "laptop",
            "laundry_machines",
            "photo_camera",
            "photocopier",
            "piano",
            "power_tools",
            "pressure_gauges",
            "printer",
            ,
            "snowboard",
            "snowmobile",
            "starter",
            "machines",
            "mainframe",
            "outboard_motor",
            "video",
            "washing_machine",
            "ski",
            "radiator",
            "radio",
            "refrigerator",
            "rv",
            "ski",
            "window",
            "zipper",
            "weighing_scale",
            "small_electric_vehicle",
        ].map((s) => s.replace(/ /g, "_"))

        const skip = ["yes", "no", "only", "brand", "assisted_self_repair", "only_sold"]
        const dloader = new OsmObjectDownloader()
        const rm = [
            "50243147100015",
            "81342677200048",
            "and overhaul",
            "repair",
            "unset",
            "сервисный_центр",
            "taller_de_michu",
            "quitandinha_g_&_a",
            "mechanika",
        ].map((v) => v.replace(/ /g, "_"))
        const objects: OsmObject[] = []
        const changesToMake: ChangeDescription[] = []
        const first = GeoOperations.centerpointCoordinates(data[0])
        for (const f of data) {
            if (
                GeoOperations.distanceBetween(first, GeoOperations.centerpointCoordinates(f)) >
                2500000
            ) {
                continue
            }
            let keyRaw = f.properties.repair
            keyRaw = replace[keyRaw] ?? keyRaw
            if (brands.some((br) => keyRaw.toLowerCase().indexOf(br.trim()) >= 0)) {
                f.properties.repair = "brand"
            }
            if (skip.indexOf(keyRaw) >= 0) {
                f.properties.repair = keyRaw
            } else {
                const r = keyRaw
                    .replace(/\/|,/g, ";")
                    .split(";")
                    .map((k) => k.trim().replace(/ /g, "_").toLowerCase())
                for (let key of r) {
                    key = replace[key] ?? key

                    if (rm.indexOf(key) >= 0) {
                        delete f.properties.repair
                        continue
                    }

                    f.properties[key + ":repair"] = "yes"
                    delete f.properties.repair
                }
            }
            if (f.properties.service === "repair") {
                delete f.properties.service
                f.properties.repair = "yes"
            }
            const id = f.properties["id"]
            const osm = await dloader.DownloadObjectAsync(id)
            if (osm === "deleted") {
                continue
            }
            objects.push(osm)
            for (const key in f.properties) {
                if (metakeys.indexOf(key) >= 0) {
                    continue
                }
                const value = f.properties[key]
                const ct = await new ChangeTagAction(id, new Tag(key, value), f.properties, {
                    changeType: "fix",
                    theme: "script",
                }).CreateChangeDescriptions()
                changesToMake.push(...ct)
                console.log(ct.map((cd) => cd.tags))
                if (f.properties.repair === undefined) {
                    const ct = await new ChangeTagAction(id, new Tag("repair", ""), f.properties, {
                        changeType: "fix",
                        theme: "script",
                    }).CreateChangeDescriptions()
                    changesToMake.push(...ct)
                }
            }
        }

        const changedObjects = changes.CreateChangesetObjects(changesToMake, objects)

        const osc = Changes.buildChangesetXML("", changedObjects)

        writeFileSync("Cleanup.osc", osc, "utf8")
    }
}

new CleanRepair().run()
