package com.pixelized.desktop.lwa.network

import com.pixelized.shared.lwa.model.alteration.AlterationJson
import com.pixelized.shared.lwa.model.campaign.CampaignJson
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson
import com.pixelized.shared.lwa.model.inventory.InventoryJson
import com.pixelized.shared.lwa.model.item.ItemJson
import com.pixelized.shared.lwa.model.map.MapJson
import com.pixelized.shared.lwa.model.tag.TagJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.rest.ApiPurseJson
import com.pixelized.shared.lwa.protocol.rest.CharacterPreviewJson

interface LwaClient {

    // Alteration

    suspend fun getAlterations(): APIResponse<List<AlterationJson>>

    suspend fun getAlteration(
        alterationId: String,
    ): APIResponse<AlterationJson?>

    suspend fun putAlteration(
        alterationJson: AlterationJson,
        create: Boolean,
    ): APIResponse<Unit>

    suspend fun deleteAlteration(
        alterationId: String,
    ): APIResponse<Unit>

    // Campaign

    suspend fun getCampaign(): APIResponse<CampaignJson>

    suspend fun putCampaignScene(
        scene: CampaignJson.SceneJson,
    ): APIResponse<Unit>

    suspend fun putCampaignCharacter(
        characterSheetId: String,
    ): APIResponse<Unit>

    suspend fun removeCampaignCharacter(
        characterSheetId: String,
    ): APIResponse<Unit>

    suspend fun putCampaignNpc(
        characterSheetId: String,
    ): APIResponse<Unit>

    suspend fun removeCampaignNpc(
        characterSheetId: String,
    ): APIResponse<Unit>

    // Character

    suspend fun getCharacterPreviews(): APIResponse<List<CharacterPreviewJson>>

    suspend fun getCharacterPreview(characterSheetId: String): APIResponse<CharacterPreviewJson>

    suspend fun getCharacter(
        characterSheetId: String,
    ): APIResponse<CharacterSheetJson>

    suspend fun putCharacter(
        sheet: CharacterSheetJson,
        create: Boolean,
    ): APIResponse<Unit>

    suspend fun putCharacterDamage(
        characterSheetId: String,
        damage: Int,
    ): APIResponse<Unit>

    suspend fun putCharacterFatigue(
        characterSheetId: String,
        fatigue: Int,
    ): APIResponse<Unit>

    suspend fun putCharacterDiminished(
        characterSheetId: String,
        diminished: Int,
    ): APIResponse<Unit>

    suspend fun putCharacterAlteration(
        characterSheetId: String,
        alterationId: String,
        active: Boolean,
    ): APIResponse<Unit>

    suspend fun deleteCharacterSheet(
        characterSheetId: String,
    ): APIResponse<Unit>

    // Items

    suspend fun getItems(): APIResponse<List<ItemJson>>

    suspend fun getItem(
        itemId: String,
    ): APIResponse<ItemJson>

    suspend fun putItem(
        itemJson: ItemJson,
        create: Boolean,
    ): APIResponse<Unit>

    suspend fun deleteItem(
        itemId: String,
    ): APIResponse<Unit>

    // Inventory

    suspend fun getInventory(
        characterSheetId: String,
    ): APIResponse<InventoryJson>

    suspend fun putInventory(
        inventory: InventoryJson,
        create: Boolean,
    ): APIResponse<Unit>

    suspend fun putInventoryPurse(
        purse: ApiPurseJson,
    ): APIResponse<Unit>

    suspend fun deleteInventory(
        characterSheetId: String,
    ): APIResponse<Unit>

    suspend fun createInventoryItem(
        characterSheetId: String,
        itemId: String,
        count: Float,
    ): APIResponse<String>

    suspend fun changeInventoryItemCount(
        characterSheetId: String,
        inventoryId: String,
        count: Float,
    ): APIResponse<Unit>

    suspend fun equipInventoryItem(
        characterSheetId: String,
        inventoryId: String,
        equip: Boolean,
    ): APIResponse<Unit>

    suspend fun consumeInventoryItem(
        characterSheetId: String,
        inventoryId: String,
    ): APIResponse<Unit>

    suspend fun deleteInventoryItem(
        characterSheetId: String,
        inventoryId: String,
    ): APIResponse<Unit>

    // Tags

    suspend fun getAlterationTags(): APIResponse<List<TagJson>>

    suspend fun getCharacterTags(): APIResponse<List<TagJson>>

    suspend fun getItemTags(): APIResponse<List<TagJson>>

    suspend fun getMaps(): APIResponse<List<MapJson>>

    suspend fun getMap(
        mapId: String,
    ): APIResponse<MapJson>

    suspend fun putMap(
        mapJson: MapJson,
        create: Boolean,
    ): APIResponse<Unit>

    suspend fun deleteMap(
        mapId: String,
    ): APIResponse<Unit>

    companion object {
        fun error(error: APIResponse<*>): Nothing = throw LwaNetworkException(error)
    }
}