import {
    MutableTacticService,
    ServiceError,
    TacticContext,
} from "./MutableTacticService.ts"
import { StepContent, StepInfoNode } from "../model/tactic/Tactic.ts"
import {
    addStepNode,
    getAvailableId,
    removeStepNode,
} from "../domains/StepsDomain.ts"

const GUEST_MODE_STEP_CONTENT_STORAGE_KEY = "guest_mode_step"
const GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY = "guest_mode_step_tree"
const GUEST_MODE_TITLE_STORAGE_KEY = "guest_mode_title"

export class LocalStorageTacticService implements MutableTacticService {
    private constructor() {}

    canBeEdited(): Promise<boolean> {
        return Promise.resolve(true)
    }

    static init(): LocalStorageTacticService {
        const root = localStorage.getItem(
            GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY,
        )

        if (root === null) {
            localStorage.setItem(
                GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY,
                JSON.stringify(<StepInfoNode>{ id: 1, children: [] }),
            )
            localStorage.setItem(
                GUEST_MODE_STEP_CONTENT_STORAGE_KEY + 1,
                JSON.stringify(<StepContent>{ components: [] }),
            )
        }

        return new LocalStorageTacticService()
    }

    async getContext(): Promise<TacticContext | ServiceError> {
        const stepsTree: StepInfoNode = JSON.parse(
            localStorage.getItem(GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY)!,
        )
        const name =
            localStorage.getItem(GUEST_MODE_TITLE_STORAGE_KEY) ??
            "Nouvelle Tactique"
        return {
            stepsTree,
            name,
            courtType: "PLAIN",
        }
    }

    async addStep(
        parent: StepInfoNode,
        content: StepContent,
    ): Promise<StepInfoNode | ServiceError> {
        const root: StepInfoNode = JSON.parse(
            localStorage.getItem(GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY)!,
        )

        const nodeId = getAvailableId(root)
        const node = { id: nodeId, children: [] }

        const resultTree = addStepNode(root, parent, node)

        localStorage.setItem(
            GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY,
            JSON.stringify(resultTree),
        )
        localStorage.setItem(
            GUEST_MODE_STEP_CONTENT_STORAGE_KEY + node.id,
            JSON.stringify(content),
        )
        return node
    }

    async getContent(step: number): Promise<StepContent | ServiceError> {
        const content = localStorage.getItem(
            GUEST_MODE_STEP_CONTENT_STORAGE_KEY + step,
        )
        return content ? JSON.parse(content) : null
    }

    async removeStep(id: number): Promise<void | ServiceError> {
        const root: StepInfoNode = JSON.parse(
            localStorage.getItem(GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY)!,
        )
        localStorage.setItem(
            GUEST_MODE_STEP_ROOT_NODE_INFO_STORAGE_KEY,
            JSON.stringify(removeStepNode(root, id)),
        )
    }

    async saveContent(
        step: number,
        content: StepContent,
    ): Promise<void | ServiceError> {
        localStorage.setItem(
            GUEST_MODE_STEP_CONTENT_STORAGE_KEY + step,
            JSON.stringify(content),
        )
    }

    async setName(name: string): Promise<void | ServiceError> {
        localStorage.setItem(GUEST_MODE_TITLE_STORAGE_KEY, name)
    }
}
