import { Store, UIEventSource } from "../../Logic/UIEventSource"
import Combine from "../Base/Combine"
import Translations from "../i18n/Translations"
import Svg from "../../Svg"
import { Tag } from "../../Logic/Tags/Tag"
import BaseUIElement from "../BaseUIElement"
import LicensePicker from "../BigComponents/LicensePicker"
import Toggle from "../Input/Toggle"
import FileSelectorButton from "../Input/FileSelectorButton"
import ImgurUploader from "../../Logic/ImageProviders/ImgurUploader"
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import { FixedUiElement } from "../Base/FixedUiElement"
import { VariableUiElement } from "../Base/VariableUIElement"
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import { Changes } from "../../Logic/Osm/Changes"
import Loading from "../Base/Loading"

export class ImageUploadFlow extends Toggle {
    private static readonly uploadCountsPerId = new Map<string, UIEventSource<number>>()

    constructor(
        tagsSource: Store<any>,
        state: {
            osmConnection: OsmConnection
            layoutToUse: LayoutConfig
            changes: Changes
            featureSwitchUserbadge: Store<boolean>
        },
        imagePrefix: string = "image",
        text: string = undefined
    ) {
        const perId = ImageUploadFlow.uploadCountsPerId
        const id = tagsSource.data.id
        if (!perId.has(id)) {
            perId.set(id, new UIEventSource<number>(0))
        }
        const uploadedCount = perId.get(id)
        const uploader = new ImgurUploader(async (url) => {
            // A file was uploaded - we add it to the tags of the object

            const tags = tagsSource.data
            let key = imagePrefix
            if (tags[imagePrefix] !== undefined) {
                let freeIndex = 0
                while (tags[imagePrefix + ":" + freeIndex] !== undefined) {
                    freeIndex++
                }
                key = imagePrefix + ":" + freeIndex
            }

            await state.changes.applyAction(
                new ChangeTagAction(tags.id, new Tag(key, url), tagsSource.data, {
                    changeType: "add-image",
                    theme: state.layoutToUse.id,
                })
            )
            console.log("Adding image:" + key, url)
            uploadedCount.data++
            uploadedCount.ping()
        })

        const licensePicker = new LicensePicker(state)
        const explanations = LicensePicker.LicenseExplanations()
        const chosenLicense = new VariableUiElement(
            licensePicker.GetValue().map((license) => explanations.get(license))
        )

        const t = Translations.t.image

        let labelContent: BaseUIElement
        if (text === undefined) {
            labelContent = Translations.t.image.addPicture
                .Clone()
                .SetClass("block align-middle mt-1 ml-3 text-4xl ")
        } else {
            labelContent = new FixedUiElement(text).SetClass(
                "block align-middle mt-1 ml-3 text-2xl "
            )
        }
        const label = new Combine([
            Svg.camera_plus_ui().SetClass("block w-12 h-12 p-1 text-4xl "),
            labelContent,
        ]).SetClass(
            "p-2 border-4 border-detail rounded-full font-bold h-full align-middle w-full flex justify-center"
        )

        const fileSelector = new FileSelectorButton(label)
        fileSelector.GetValue().addCallback((filelist) => {
            if (filelist === undefined || filelist.length === 0) {
                return
            }

            for (var i = 0; i < filelist.length; i++) {
                const sizeInBytes = filelist[i].size
                console.log(filelist[i].name + " has a size of " + sizeInBytes + " Bytes")
                if (sizeInBytes > uploader.maxFileSizeInMegabytes * 1000000) {
                    alert(
                        Translations.t.image.toBig.Subs({
                            actual_size: Math.floor(sizeInBytes / 1000000) + "MB",
                            max_size: uploader.maxFileSizeInMegabytes + "MB",
                        }).txt
                    )
                    return
                }
            }

            console.log("Received images from the user, starting upload")
            const license = licensePicker.GetValue()?.data ?? "CC0"

            const tags = tagsSource.data

            const layout = state?.layoutToUse
            let matchingLayer: LayerConfig = undefined
            for (const layer of layout?.layers ?? []) {
                if (layer.source.osmTags.matchesProperties(tags)) {
                    matchingLayer = layer
                    break
                }
            }

            const title =
                matchingLayer?.title?.GetRenderValue(tags)?.Subs(tags)?.ConstructElement()
                    ?.textContent ??
                tags.name ??
                "https//osm.org/" + tags.id
            const description = [
                "author:" + state.osmConnection.userDetails.data.name,
                "license:" + license,
                "osmid:" + tags.id,
            ].join("\n")

            uploader.uploadMany(title, description, filelist)
        })

        const uploadFlow: BaseUIElement = new Combine([
            new VariableUiElement(
                uploader.queue
                    .map((q) => q.length)
                    .map((l) => {
                        if (l == 0) {
                            return undefined
                        }
                        if (l == 1) {
                            return new Loading(t.uploadingPicture).SetClass("alert")
                        } else {
                            return new Loading(
                                t.uploadingMultiple.Subs({ count: "" + l })
                            ).SetClass("alert")
                        }
                    })
            ),
            new VariableUiElement(
                uploader.failed
                    .map((q) => q.length)
                    .map((l) => {
                        if (l == 0) {
                            return undefined
                        }
                        console.log(l)
                        return t.uploadFailed.SetClass("block alert")
                    })
            ),
            new VariableUiElement(
                uploadedCount.map((l) => {
                    if (l == 0) {
                        return undefined
                    }
                    if (l == 1) {
                        return t.uploadDone.Clone().SetClass("thanks block")
                    }
                    return t.uploadMultipleDone.Subs({ count: l }).SetClass("thanks block")
                })
            ),

            fileSelector,
            Translations.t.image.respectPrivacy.Clone().SetStyle("font-size:small;"),
            licensePicker,
            chosenLicense.SetClass("subtle text-sm"),
        ]).SetClass("flex flex-col image-upload-flow mt-4 mb-8 text-center")

        const pleaseLoginButton = t.pleaseLogin
            .Clone()
            .onClick(() => state.osmConnection.AttemptLogin())
            .SetClass("login-button-friendly")
        super(
            new Toggle(
                /*We can show the actual upload button!*/
                uploadFlow,
                /* User not logged in*/ pleaseLoginButton,
                state?.osmConnection?.isLoggedIn
            ),
            undefined /* Nothing as the user badge is disabled*/,
            state?.featureSwitchUserbadge
        )
    }
}