#![allow(dead_code)]
use std::collections::HashMap;
use std::convert::Into;
use serde::{Serialize, Deserialize};
use libpso::character::settings;
use libpso::util::vec_to_array;
use crate::entity::account::*;
use crate::entity::character::*;
use crate::entity::item::*;
use crate::ship::map::MapArea;

#[derive(Debug, sqlx::FromRow)]
pub struct PgUserAccount {
    id: i32,
    username: String,
    password: String,
    banned: Option<chrono::DateTime<chrono::Utc>>,
    muted: Option<chrono::DateTime<chrono::Utc>>,
    created_at: chrono::DateTime<chrono::Utc>,
    flags: i32,
    activated: bool,
    at_login: bool,
    at_character: bool,
    at_ship: bool,
}

impl From<PgUserAccount> for UserAccountEntity {
    fn from(other: PgUserAccount) -> UserAccountEntity {
        UserAccountEntity {
            id: UserAccountId(other.id as u32),
            username: other.username,
            password: other.password,
            banned_until: other.banned,
            muted_until: other.muted,
            created_at: other.created_at,
            flags: other.flags as u32,
            guildcard: other.id as u32 + 1,
            team_id: None,
            activated: other.activated,
            at_login: other.at_login,
            at_character: other.at_character,
            at_ship: other.at_ship,
        }
    }
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgUserSettings {
    id: i32,
    user_account: i32,
    blocked_users: Vec<u8>, //[u32; 0x1E],
    keyboard_config: Vec<u8>, //[u8; 0x16C],
    gamepad_config: Vec<u8>, //[u8; 0x38],
    option_flags: i32,
    shortcuts: Vec<u8>, //[u8; 0xA40],
    symbol_chats: Vec<u8>, //[u8; 0x4E0],
    team_name: Vec<u8>, //[u16; 0x10],
}

impl From<PgUserSettings> for UserSettingsEntity {
    fn from(other: PgUserSettings) -> UserSettingsEntity {
        UserSettingsEntity {
            id: UserSettingsId(other.id as u32),
            user_id: UserAccountId(other.user_account as u32),
            settings: settings::UserSettings {
                blocked_users: vec_to_array(other.blocked_users.chunks(4).map(|b| u32::from_le_bytes([b[0], b[1], b[2], b[3]])).collect()),
                keyboard_config: vec_to_array(other.keyboard_config),
                gamepad_config: vec_to_array(other.gamepad_config),
                option_flags: other.option_flags as u32,
                shortcuts: vec_to_array(other.shortcuts),
                symbol_chats: vec_to_array(other.symbol_chats),
                team_name: vec_to_array(other.team_name.chunks(2).map(|b| u16::from_le_bytes([b[0], b[1]])).collect()),
            }
        }
    }
}

#[derive(sqlx::Type, Debug)]
#[sqlx(rename_all = "lowercase")]
pub enum PgCharacterClass {
    HUmar,
    HUnewearl,
    HUcast,
    HUcaseal,
    RAmar,
    RAmarl,
    RAcast,
    RAcaseal,
    FOmar,
    FOmarl,
    FOnewm,
    FOnewearl,
}

impl From<PgCharacterClass> for CharacterClass {
    fn from(other: PgCharacterClass) -> CharacterClass {
        match other{
            PgCharacterClass::HUmar => CharacterClass::HUmar,
            PgCharacterClass::HUnewearl => CharacterClass::HUnewearl,
            PgCharacterClass::HUcast => CharacterClass::HUcast,
            PgCharacterClass::HUcaseal => CharacterClass::HUcaseal,
            PgCharacterClass::RAmar => CharacterClass::RAmar,
            PgCharacterClass::RAmarl => CharacterClass::RAmarl,
            PgCharacterClass::RAcast => CharacterClass::RAcast,
            PgCharacterClass::RAcaseal => CharacterClass::RAcaseal,
            PgCharacterClass::FOmar => CharacterClass::FOmar,
            PgCharacterClass::FOmarl => CharacterClass::FOmarl,
            PgCharacterClass::FOnewm => CharacterClass::FOnewm,
            PgCharacterClass::FOnewearl => CharacterClass::FOnewearl,
        }
    }
}

impl From<CharacterClass> for PgCharacterClass {
    fn from(other: CharacterClass) -> PgCharacterClass {
        match other {
            CharacterClass::HUmar => PgCharacterClass::HUmar,
            CharacterClass::HUnewearl => PgCharacterClass::HUnewearl,
            CharacterClass::HUcast => PgCharacterClass::HUcast,
            CharacterClass::HUcaseal => PgCharacterClass::HUcaseal,
            CharacterClass::RAmar => PgCharacterClass::RAmar,
            CharacterClass::RAmarl => PgCharacterClass::RAmarl,
            CharacterClass::RAcast => PgCharacterClass::RAcast,
            CharacterClass::RAcaseal => PgCharacterClass::RAcaseal,
            CharacterClass::FOmar => PgCharacterClass::FOmar,
            CharacterClass::FOmarl => PgCharacterClass::FOmarl,
            CharacterClass::FOnewm => PgCharacterClass::FOnewm,
            CharacterClass::FOnewearl => PgCharacterClass::FOnewearl,
        }
    }
}

#[derive(sqlx::Type, Debug)]
#[sqlx(rename_all = "lowercase")]
pub enum PgSectionId {
    Viridia,
    Greenill,
    Skyly,
    Bluefull,
    Purplenum,
    Pinkal,
    Redria,
    Oran,
    Yellowboze,
    Whitill,
}

impl From<PgSectionId> for SectionID {
    fn from(other: PgSectionId) -> SectionID {
        match other {
            PgSectionId::Viridia => SectionID::Viridia,
            PgSectionId::Greenill => SectionID::Greenill,
            PgSectionId::Skyly => SectionID::Skyly,
            PgSectionId::Bluefull => SectionID::Bluefull,
            PgSectionId::Purplenum => SectionID::Purplenum,
            PgSectionId::Pinkal => SectionID::Pinkal,
            PgSectionId::Redria => SectionID::Redria,
            PgSectionId::Oran => SectionID::Oran,
            PgSectionId::Yellowboze => SectionID::Yellowboze,
            PgSectionId::Whitill => SectionID::Whitill,
        }
    }
}

impl From<SectionID> for PgSectionId {
    fn from(other: SectionID) -> PgSectionId {
        match other {
            SectionID::Viridia => PgSectionId::Viridia,
            SectionID::Greenill => PgSectionId::Greenill,
            SectionID::Skyly => PgSectionId::Skyly,
            SectionID::Bluefull => PgSectionId::Bluefull,
            SectionID::Purplenum => PgSectionId::Purplenum,
            SectionID::Pinkal => PgSectionId::Pinkal,
            SectionID::Redria => PgSectionId::Redria,
            SectionID::Oran => PgSectionId::Oran,
            SectionID::Yellowboze => PgSectionId::Yellowboze,
            SectionID::Whitill => PgSectionId::Whitill,
        }
    }
}


#[derive(Debug, sqlx::FromRow)]
pub struct PgCharacter {
    pub id: i32,
    user_account: i32,
    pub slot: i16,
    name: String,
    exp: i32,
    class: String,
    section_id: String,

    costume: i16,
    skin: i16,
    face: i16,
    head: i16,
    hair: i16,
    hair_r: i16,
    hair_g: i16,
    hair_b: i16,
    prop_x: f32,
    prop_y: f32,

    techs: Vec<u8>,
    
    config: Vec<u8>,
    infoboard: String,
    guildcard: String,
    option_flags: i32,
    
    power: i16,
    mind: i16,
    def: i16,
    evade: i16,
    luck: i16,
    hp: i16,
    tp: i16,

    tech_menu: Vec<u8>,
    keyboard_config: Vec<u8>,
    gamepad_config: Vec<u8>,

    playtime: i32,
}

impl From<PgCharacter> for CharacterEntity {
    fn from(other: PgCharacter) -> CharacterEntity {
        CharacterEntity {
            id: CharacterEntityId(other.id as u32),
            user_id: UserAccountId(other.user_account as u32),
            slot: other.slot as u32,
            name: other.name,
            exp: other.exp as u32,
            char_class: other.class.parse().unwrap(),
            section_id: other.section_id.parse().unwrap(),
            appearance: CharacterAppearance {
                costume: other.costume as u16,
                skin: other.skin as u16,
                face: other.face as u16,
                head: other.head as u16,
                hair: other.hair as u16,
                hair_r: other.hair_r as u16,
                hair_g: other.hair_g as u16,
                hair_b: other.hair_b as u16,
                prop_x: other.prop_x,
                prop_y: other.prop_y,
            },
            techs: CharacterTechniques {
                techs: other.techs.iter().enumerate().take(19).filter(|(_, t)| **t != 0xFF).map(|(i, t)| (tech::Technique::from_value(i as u8), TechLevel(*t)) ).collect()
            },
            config: CharacterConfig {
                raw_data: vec_to_array(other.config)
            },
            info_board: CharacterInfoboard {
                board: libpso::utf8_to_utf16_array!(other.infoboard, 172),
            },
            guildcard: CharacterGuildCard {
                description: other.guildcard,
            },
            option_flags: other.option_flags as u32,
            materials: CharacterMaterials {
                power: other.power as u32,
                mind: other.mind as u32,
                def: other.def as u32,
                evade: other.evade as u32,
                luck: other.luck as u32,
                hp: other.hp as u32,
                tp: other.tp as u32,
            },
            tech_menu: CharacterTechMenu {
                tech_menu: vec_to_array(other.tech_menu)
            },
            keyboard_config: CharacterKeyboardConfig {
                keyboard_config: vec_to_array(other.keyboard_config)
            },
            gamepad_config: CharacterGamepadConfig {
                gamepad_config: vec_to_array(other.gamepad_config)
            },
            playtime: other.playtime as u32,
        }
    }
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgGuildCard {
}



#[derive(Debug, Serialize, Deserialize)]
pub struct PgWeapon {
    weapon: weapon::WeaponType,
    special: Option<weapon::WeaponSpecial>,
    grind: u8,
    attrs: HashMap<weapon::Attribute, i8>,
    tekked: bool,
}

impl From<weapon::Weapon> for PgWeapon {
    fn from(other: weapon::Weapon) -> PgWeapon {
        PgWeapon {
            weapon: other.weapon,
            special: other.special,
            grind: other.grind,
            attrs: other.attrs.iter().flatten().map(|attr| (attr.attr, attr.value)).collect(),
            tekked: other.tekked,
        }
    }
}

impl From<PgWeapon> for weapon::Weapon {
    fn from(other: PgWeapon) -> weapon::Weapon {
        let mut attrs: [Option<weapon::WeaponAttribute>; 3] = [None; 3];
        for (attr, (atype, value)) in attrs.iter_mut().zip(other.attrs.iter()) {
            *attr = Some(weapon::WeaponAttribute {
                attr: *atype,
                value: *value
            });
        }
        
        weapon::Weapon {
            weapon: other.weapon,
            special: other.special,
            grind: other.grind,
            attrs,
            tekked: other.tekked,
        }
    }
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgWeaponModifier {
    pub weapon: i32,
    pub modifier: sqlx::types::Json<weapon::WeaponModifier>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PgArmor {
    armor: armor::ArmorType,
    dfp: u8,
    evp: u8,
    slots: u8,
}

impl From<armor::Armor> for PgArmor {
    fn from(other: armor::Armor) -> PgArmor {
        PgArmor {
            armor: other.armor,
            dfp: other.dfp,
            evp: other.evp,
            slots: other.slots,
        }
    }
}

impl From<PgArmor> for armor::Armor {
    fn from(other: PgArmor) -> armor::Armor {
        armor::Armor {
            armor: other.armor,
            dfp: other.dfp,
            evp: other.evp,
            slots: other.slots,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PgShield {
    shield: shield::ShieldType,
    dfp: u8,
    evp: u8,
}

impl From<shield::Shield> for PgShield {
    fn from(other: shield::Shield) -> PgShield {
        PgShield {
            shield: other.shield,
            dfp: other.dfp,
            evp: other.evp,
        }
    }
}

impl From<PgShield> for shield::Shield {
    fn from(other: PgShield) -> shield::Shield {
        shield::Shield {
            shield: other.shield,
            dfp: other.dfp,
            evp: other.evp,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PgUnit {
    unit: unit::UnitType,
    modifier: Option<unit::UnitModifier>,
}

impl From<unit::Unit> for PgUnit {
    fn from(other: unit::Unit) -> PgUnit {
        PgUnit {
            unit: other.unit,
            modifier: other.modifier,
        }
    }
}

impl From<PgUnit> for unit::Unit {
    fn from(other: PgUnit) -> unit::Unit {
        unit::Unit {
            unit: other.unit,
            modifier: other.modifier,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PgTool {
    pub tool: tool::ToolType,
}

impl From<tool::Tool> for PgTool {
    fn from(other: tool::Tool) -> PgTool {
        PgTool {
            tool: other.tool,
        }
    }
}

impl From<PgTool> for tool::Tool {
    fn from(other: PgTool) -> tool::Tool {
        tool::Tool {
            tool: other.tool,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PgTechDisk {
    tech: tech::Technique,
    level: u32,
}

impl From<tech::TechniqueDisk> for PgTechDisk {
    fn from(other: tech::TechniqueDisk) -> PgTechDisk {
        PgTechDisk {
            tech: other.tech,
            level: other.level,
        }
    }
}

impl From<PgTechDisk> for tech::TechniqueDisk {
    fn from(other: PgTechDisk) -> tech::TechniqueDisk {
        tech::TechniqueDisk {
            tech: other.tech,
            level: other.level
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PgMag {
    mag: mag::MagType,
    synchro: u8,
    color: u8,
}

impl From<mag::Mag> for PgMag {
    fn from(other: mag::Mag) -> PgMag {
        PgMag {
            mag: other.mag,
            synchro: other.synchro,
            color: other.color,
        }
    }
}

impl From<PgMag> for mag::Mag {
    fn from(other: PgMag) -> mag::Mag {
        /*mag::Mag {
            mag: self.mag,
            synchro: self.synchro,
            color: self.color,
            def: 500,
            pow: 0,
            dex: 0,
            mnd: 0,
            iq: 0,
            photon_blast: [None; 3],
            class: CharacterClass::HUmar,
            id: SectionID::Viridia,
    }*/
        let mut mag = mag::Mag::baby_mag(other.color as u16);
        mag.mag = other.mag;
        mag.synchro = other.synchro;
        mag
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PgESWeapon {
    esweapon: esweapon::ESWeaponType,
    special: Option<esweapon::ESWeaponSpecial>,
    name: String,
    grind: u8,
}

impl From<esweapon::ESWeapon> for PgESWeapon {
    fn from(other: esweapon::ESWeapon) -> PgESWeapon {
        PgESWeapon {
            esweapon: other.esweapon,
            special: other.special,
            name: other.name,
            grind: other.grind,
        }
    }
}

impl From<PgESWeapon> for esweapon::ESWeapon {
    fn from(other: PgESWeapon) -> esweapon::ESWeapon {
        esweapon::ESWeapon {
            esweapon: other.esweapon,
            special: other.special,
            name: other.name,
            grind: other.grind,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub enum PgItemDetail {
    Weapon(PgWeapon),
    Armor(PgArmor),
    Shield(PgShield),
    Unit(PgUnit),
    Tool(PgTool),
    TechDisk(PgTechDisk),
    Mag(PgMag),
    ESWeapon(PgESWeapon),
}

impl From<ItemDetail> for PgItemDetail {
    fn from(other: ItemDetail) -> PgItemDetail {
        match other {
            ItemDetail::Weapon(weapon) => PgItemDetail::Weapon(weapon.into()),
            ItemDetail::Armor(armor) => PgItemDetail::Armor(armor.into()),
            ItemDetail::Shield(shield) => PgItemDetail::Shield(shield.into()),
            ItemDetail::Unit(unit) => PgItemDetail::Unit(unit.into()),
            ItemDetail::Tool(tool) => PgItemDetail::Tool(tool.into()),
            ItemDetail::TechniqueDisk(tech_disk) => PgItemDetail::TechDisk(tech_disk.into()),
            ItemDetail::Mag(mag) => PgItemDetail::Mag(mag.into()),
            ItemDetail::ESWeapon(esweapon) => PgItemDetail::ESWeapon(esweapon.into()),
        }
    }
}

impl From<PgItemDetail> for ItemDetail {
    fn from(other: PgItemDetail) -> ItemDetail {
        match other {
            PgItemDetail::Weapon(weapon) => ItemDetail::Weapon(weapon.into()),
            PgItemDetail::Armor(armor) => ItemDetail::Armor(armor.into()),
            PgItemDetail::Shield(shield) => ItemDetail::Shield(shield.into()),
            PgItemDetail::Unit(unit) => ItemDetail::Unit(unit.into()),
            PgItemDetail::Tool(tool) => ItemDetail::Tool(tool.into()),
            PgItemDetail::TechDisk(tech_disk) => ItemDetail::TechniqueDisk(tech_disk.into()),
            PgItemDetail::Mag(mag) => ItemDetail::Mag(mag.into()),
            PgItemDetail::ESWeapon(esweapon) => ItemDetail::ESWeapon(esweapon.into()),
        }
    }
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgItem {
    pub id: i32,
    pub item: sqlx::types::Json<PgItemDetail>,
}


#[derive(Debug, Serialize, Deserialize)]
pub enum PgItemNoteDetail {
    CharacterCreation {
        character_id: u32,
    },
    EnemyDrop {
        character_id: u32,
        map_area: MapArea,
        x: f32,
        y: f32,
        z: f32,
    },
    Pickup {
        character_id: u32,
    },
    PlayerDrop {
        character_id: u32,
        map_area: MapArea,
        x: f32,
        y: f32,
        z: f32,
    },
    Consumed,
    FedToMag {
        mag: u32,
    },
    BoughtAtShop {
        character_id: u32,
    },
    SoldToShop,
    Trade {
        trade_id: u32,
        character_to: u32,
        character_from: u32,
    },
    Withdraw {
        character_id: u32,
        bank: String,
    },
    Deposit {
        character_id: u32,
        bank: String,
    }
}

impl From<ItemNote> for PgItemNoteDetail {
    fn from(other: ItemNote) -> PgItemNoteDetail {
        match other {
            ItemNote::CharacterCreation{character_id} => PgItemNoteDetail::CharacterCreation {
                character_id: character_id.0,
            },
            ItemNote::EnemyDrop{character_id, map_area, x, y, z} => PgItemNoteDetail::EnemyDrop {
                character_id: character_id.0,
                map_area,
                x,y,z,
            },
            ItemNote::Pickup{character_id} => PgItemNoteDetail::Pickup {
                character_id: character_id.0,
            },
            ItemNote::PlayerDrop{character_id, map_area, x, y, z} => PgItemNoteDetail::PlayerDrop {
                character_id: character_id.0,
                map_area,
                x,y,z,
            },
            ItemNote::Consumed => PgItemNoteDetail::Consumed,
            ItemNote::FedToMag{mag} => PgItemNoteDetail::FedToMag{
                mag: mag.0
            },
            ItemNote::BoughtAtShop{character_id} => PgItemNoteDetail::BoughtAtShop {
                character_id: character_id.0,
            },
            ItemNote::SoldToShop => PgItemNoteDetail::SoldToShop,
            ItemNote::Trade{trade_id, character_to, character_from} => PgItemNoteDetail::Trade {
                trade_id: trade_id.0,
                character_to: character_to.0,
                character_from: character_from.0,
            },
            ItemNote::Withdraw{character_id, bank} => {
                PgItemNoteDetail::Withdraw {
                    character_id: character_id.0,
                    bank: bank.0,
                }
            },
            ItemNote::Deposit{character_id, bank} => {
                PgItemNoteDetail::Deposit {
                    character_id: character_id.0,
                    bank: bank.0,
                }
            }
        }
    }
}

impl From<PgItemNoteDetail> for ItemNote {
    fn from(other: PgItemNoteDetail) -> ItemNote {
        match other {
            PgItemNoteDetail::CharacterCreation{character_id} => ItemNote::CharacterCreation {
                character_id: CharacterEntityId(character_id as u32),
            },
            PgItemNoteDetail::EnemyDrop{character_id, map_area, x, y, z} => ItemNote::EnemyDrop {
                character_id: CharacterEntityId(character_id as u32),
                map_area,
                x,y,z,
            },
            PgItemNoteDetail::Pickup{character_id} => ItemNote::Pickup {
                character_id: CharacterEntityId(character_id as u32),
            },
            PgItemNoteDetail::PlayerDrop{character_id, map_area, x, y, z} => ItemNote::PlayerDrop {
                character_id: CharacterEntityId(character_id as u32),
                map_area,
                x,y,z,
            },
            PgItemNoteDetail::Consumed => ItemNote::Consumed,
            PgItemNoteDetail::FedToMag{mag} => ItemNote::FedToMag{
                mag: ItemEntityId(mag)
            },
            PgItemNoteDetail::BoughtAtShop{character_id} => ItemNote::BoughtAtShop {
                character_id: CharacterEntityId(character_id),
            },
            PgItemNoteDetail::SoldToShop => ItemNote::SoldToShop,
            PgItemNoteDetail::Trade {trade_id, character_to, character_from} => ItemNote::Trade {
                trade_id: TradeId(trade_id as u32),
                character_to: CharacterEntityId(character_to as u32),
                character_from: CharacterEntityId(character_from as u32),
            },
            PgItemNoteDetail::Withdraw{character_id, bank} => ItemNote::Withdraw {
                character_id: CharacterEntityId(character_id as u32),
                bank: BankName(bank),
            },
            PgItemNoteDetail::Deposit{character_id, bank} => ItemNote::Deposit {
                character_id: CharacterEntityId(character_id as u32),
                bank: BankName(bank),
            },
        }
    }
}


#[derive(Debug, sqlx::FromRow)]
pub struct PgItemNote {
    //pub id: i32,
    pub note: sqlx::types::Json<PgItemNoteDetail>,
    created_at: chrono::DateTime<chrono::Utc>,
}


#[derive(Debug, Serialize, Deserialize)]
pub enum PgMagModifierDetail {
    FeedMag(i32),
    BankMag,
    MagCell(i32),
    OwnerChange(CharacterClass, SectionID)
}

impl From<mag::MagModifier> for PgMagModifierDetail {
    fn from(other: mag::MagModifier) -> PgMagModifierDetail {
        match other {
            mag::MagModifier::FeedMag{food} => PgMagModifierDetail::FeedMag(food.0 as i32),
            mag::MagModifier::BankMag => PgMagModifierDetail::BankMag,
            mag::MagModifier::MagCell(cell) => PgMagModifierDetail::MagCell(cell.0 as i32),
            mag::MagModifier::OwnerChange(class, section_id) => PgMagModifierDetail::OwnerChange(class, section_id),
        }
    }
}

impl From<PgMagModifierDetail> for mag::MagModifier {
    fn from(other: PgMagModifierDetail) -> mag::MagModifier {
        match other {
            PgMagModifierDetail::FeedMag(food) => mag::MagModifier::FeedMag{food: ItemEntityId(food as u32)},
            PgMagModifierDetail::BankMag => mag::MagModifier::BankMag,
            PgMagModifierDetail::MagCell(cell) => mag::MagModifier::MagCell(ItemEntityId(cell as u32)),
            PgMagModifierDetail::OwnerChange(class, section_id) => mag::MagModifier::OwnerChange(class, section_id),
        }
    }
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgMagModifier {
    mag: i32,
    pub modifier: sqlx::types::Json<PgMagModifierDetail>,
    created_at: chrono::DateTime<chrono::Utc>,
}


#[derive(Debug, sqlx::FromRow)]
pub struct PgItemEntity {
    pub id: i32,
    pub item: sqlx::types::Json<PgItemDetail>,
}

/*
#[derive(Debug, sqlx::FromRow)]
pub struct PgItemWithLocation {
    pub id: i32,
    pub item: sqlx::types::Json<PgItemDetail>,
    pub location: sqlx::types::Json<PgItemLocationDetail>,
}
*/

impl From<PgItemEntity> for ItemEntity {
    fn from(other: PgItemEntity) -> ItemEntity {
        ItemEntity {
            id: ItemEntityId(other.id as u32),
            item: other.item.0.into(),
        }
    }
}


#[derive(Debug, sqlx::FromRow)]
pub struct PgMagModifierWithParameters {
    pub mag: i32,
    pub modifier: sqlx::types::Json<PgMagModifierDetail>,
    pub feed: Option<sqlx::types::Json<PgTool>>,
    pub cell: Option<sqlx::types::Json<PgTool>>,
}


#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PgInventoryItemEntity {
    Individual(i32),
    Stacked(Vec<i32>),
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgInventoryEntity {
    pub pchar: i32,
    pub items: sqlx::types::Json<Vec<PgInventoryItemEntity>>,
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgBankEntity {
    pub pchar: i32,
    pub items: sqlx::types::Json<Vec<PgInventoryItemEntity>>,
    pub name: String,
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgEquipped {
    pchar: i32,
    weapon: Option<i32>,
    armor: Option<i32>,
    shield: Option<i32>,
    unit0: Option<i32>,
    unit1: Option<i32>,
    unit2: Option<i32>,
    unit3: Option<i32>,
    mag: Option<i32>,
}

impl From<PgEquipped> for EquippedEntity{
    fn from(other: PgEquipped) -> EquippedEntity {
        EquippedEntity {
            weapon: other.weapon.map(|i| ItemEntityId(i as u32)),
            armor: other.armor.map(|i| ItemEntityId(i as u32)),
            shield: other.shield.map(|i| ItemEntityId(i as u32)),
            unit: [other.unit0.map(|i| ItemEntityId(i as u32)),
                   other.unit1.map(|i| ItemEntityId(i as u32)),
                   other.unit2.map(|i| ItemEntityId(i as u32)),
                   other.unit3.map(|i| ItemEntityId(i as u32)),
            ],
            mag: other.mag.map(|i| ItemEntityId(i as u32)),
        }
    }
}

impl From<(CharacterEntityId, EquippedEntity)> for PgEquipped {
    fn from(char_equips: (CharacterEntityId, EquippedEntity)) -> PgEquipped {
        PgEquipped {
            pchar: (char_equips.0).0 as i32,
            weapon: char_equips.1.weapon.map(|i| i.0 as i32),
            armor: char_equips.1.armor.map(|i| i.0 as i32),
            shield: char_equips.1.shield.map(|i| i.0 as i32),
            unit0: char_equips.1.unit[0].map(|i| i.0 as i32),
            unit1: char_equips.1.unit[1].map(|i| i.0 as i32),
            unit2: char_equips.1.unit[2].map(|i| i.0 as i32),
            unit3: char_equips.1.unit[3].map(|i| i.0 as i32),
            mag: char_equips.1.mag.map(|i| i.0 as i32),
        }
    }
}

#[derive(Debug, sqlx::FromRow)]
pub struct PgTradeEntity {
    id: i32,
    character1: i32,
    character2: i32,
}

impl From<PgTradeEntity> for TradeEntity {
    fn from(other: PgTradeEntity) -> TradeEntity {
        TradeEntity {
            id: TradeId(other.id as u32),
            character1: CharacterEntityId(other.character1 as u32),
            character2: CharacterEntityId(other.character2 as u32),
        }
    }
}