"""
Project:    PARTS Website
Author:     Edward Middleton-Smith
            Precision And Research Technology Systems Limited

Technology: Business Objects
Feature:    MTG Game Round Player Damage Business Object
"""

# internal
from business_objects.base import Base
from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
import lib.argument_validation as av
from extensions import db
from helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar
from sqlalchemy import Uuid
from sqlalchemy.types import Text, Boolean


class MTG_Game_Round_Player_Damage(SQLAlchemy_ABC, Base):
    ATTR_DAMAGE_ID: ClassVar[str] = 'damage_id'
    ATTR_PLAYER_ID: ClassVar[str] = 'player_id'
    ATTR_ROUND_ID: ClassVar[str] = 'round_id'
    ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID: ClassVar[str] = 'received_from_commander_player_id'
    FLAG_COMMANDER_DEATHS: ClassVar[str] = 'commander_deaths'
    FLAG_DAMAGE: ClassVar[str] = 'damage'
    FLAG_IS_ELIMINATED: ClassVar[str] = 'is_eliminated'
    FLAG_LIFE_GAIN: ClassVar[str] = 'life_gain'
    FLAG_LIFE_LOSS: ClassVar[str] = 'life_loss'
    NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_DAMAGE_ID
    NAME_ATTR_OPTION_TEXT: ClassVar[str] = ATTR_DAMAGE_ID

    __tablename__ = 'tcg_mtg_game_round_player_damage'
    __table_args__ = { 'extend_existing': True }

    damage_id = db.Column(db.Integer, primary_key=True)
    round_id = db.Column(db.Integer)
    player_id = db.Column(db.Integer)
    received_from_commander_player_id = db.Column(db.Integer)
    life_gain = db.Column(db.Integer)
    life_loss = db.Column(db.Integer)
    commander_deaths = db.Column(db.Integer)
    is_eliminated = db.Column(db.Boolean)
    active = db.Column(db.Boolean)
    created_on = db.Column(db.DateTime)
    created_by_user_id = db.Column(db.Integer)
    updated_last_on = db.Column(db.DateTime)
    updated_last_by_user_id = db.Column(db.Integer)
    change_set_id = db.Column(db.Integer)

    def __init__(self):
        self.damage_id = 0
        self.is_new = False
        super().__init__()

    @classmethod
    def from_db_mtg_game_round_player_damage(cls, query_row):
        _m = f'{cls.__qualname__}.from_db_mtg_game_round_player_damage'
        damage = cls()
        damage.damage_id = query_row[0]
        damage.round_id = query_row[1]
        damage.player_id = query_row[2]
        damage.received_from_commander_player_id = query_row[3]
        damage.life_gain = query_row[4]
        damage.life_loss = query_row[5]
        damage.commander_deaths = query_row[6]
        damage.is_eliminated = av.input_bool(query_row[7], cls.FLAG_IS_ELIMINATED, _m)
        damage.active = av.input_bool(query_row[8], cls.FLAG_ACTIVE, _m)
        damage.created_on = query_row[9]
        damage.created_by_user_id = query_row[10]
        return damage

    @classmethod
    def from_json(cls, json):
        _m = f'{cls.__qualname__}.from_json'
        damage = cls()
        if json is None: return damage
        damage.damage_id = json.get(cls.ATTR_DAMAGE_ID, -1)
        damage.round_id = json.get(cls.ATTR_ROUND_ID, None)
        damage.player_id = json.get(cls.ATTR_PLAYER_ID, None)
        damage.received_from_commander_player_id = json.get(cls.ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID, None)
        damage.life_gain = json.get(cls.FLAG_LIFE_GAIN, 0)
        damage.life_loss = json.get(cls.FLAG_LIFE_LOSS, 0)
        damage.commander_deaths = json.get(cls.FLAG_COMMANDER_DEATHS, 0)
        damage.is_eliminated = json.get(cls.FLAG_IS_ELIMINATED, False)
        damage.active = av.input_bool(json.get(cls.FLAG_ACTIVE, True), cls.FLAG_ACTIVE, _m)
        damage.created_on = json.get(cls.FLAG_CREATED_ON, None)
        damage.created_by_user_id = json.get(Base.ATTR_USER_ID, None)
        return damage

    def to_json(self):
        as_json = {
            **self.get_shared_json_attributes(self)
            , self.ATTR_DAMAGE_ID: self.damage_id
            , self.ATTR_ROUND_ID: self.round_id
            , self.ATTR_PLAYER_ID: self.player_id
            , self.ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID: self.received_from_commander_player_id
            , self.FLAG_LIFE_GAIN: self.life_gain
            , self.FLAG_LIFE_LOSS: self.life_loss
            , self.FLAG_COMMANDER_DEATHS: self.commander_deaths
            , self.FLAG_IS_ELIMINATED: self.is_eliminated
            , self.FLAG_ACTIVE: self.active
            , self.FLAG_CREATED_ON: self.created_on
            , Base.ATTR_USER_ID: self.created_by_user_id
        }
        return as_json

    def __repr__(self):
        return f'''
{self.__class__.__name__}(
    {self.ATTR_DAMAGE_ID}: {self.damage_id}
    {self.ATTR_ROUND_ID}: {self.round_id}
    {self.ATTR_PLAYER_ID}: {self.player_id}
    {self.ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID}: {self.received_from_commander_player_id}
    {self.FLAG_LIFE_GAIN}: {self.life_gain}
    {self.FLAG_LIFE_LOSS}: {self.life_loss}
    {self.FLAG_COMMANDER_DEATHS}: {self.commander_deaths}
    {self.FLAG_IS_ELIMINATED}: {self.is_eliminated}
    {self.FLAG_ACTIVE}: {self.active}
    {self.FLAG_CREATED_ON}: {self.created_on}
    {Base.ATTR_USER_ID}: {self.created_by_user_id}
)
            '''

class MTG_Game_Round_Player_Damage_Temp(db.Model, Base):
    __tablename__ = 'tcg_mtg_game_round_player_damage_temp'
    __table_args__ = { 'extend_existing': True }
    temp_id = db.Column(db.Integer, primary_key=True)
    damage_id = db.Column(db.Integer)
    round_id = db.Column(db.Integer)
    player_id = db.Column(db.Integer)
    received_from_commander_player_id = db.Column(db.Integer)
    life_gain = db.Column(db.Integer)
    life_loss = db.Column(db.Integer)
    commander_deaths = db.Column(db.Integer)
    is_eliminated = db.Column(db.Boolean)
    active = db.Column(db.Boolean)
    created_on = db.Column(db.DateTime)
    guid = db.Column(Uuid)

    def __init__(self):
        super().__init__()

    @classmethod
    def from_damage(cls, damage, guid):
        _m = 'MTG_Game_Round_Player_Damage_Temp.from_damage'
        temp = cls()
        temp.damage_id = damage.damage_id
        temp.round_id = damage.round_id
        temp.player_id = damage.player_id
        temp.received_from_commander_player_id = damage.received_from_commander_player_id
        temp.life_gain = damage.life_gain
        temp.life_loss = damage.life_loss
        temp.commander_deaths = damage.commander_deaths
        temp.is_eliminated = damage.is_eliminated
        temp.active = damage.active
        temp.created_on = damage.created_on
        temp.guid = guid
        return temp


class Parameters_MTG_Game_Round_Player_Damage(Get_Many_Parameters_Base):
    get_all_game: bool
    get_inactive_game: bool
    game_ids: str
    require_all_id_filters_met: bool
    require_any_id_filters_met: bool

    @classmethod
    def get_default(cls, user_id_session):
        return cls(
              get_all_game = True
            , get_inactive_game = False
            , game_ids = ''
            , require_all_id_filters_met = True
            , require_any_id_filters_met = True
        )

    @classmethod
    def from_json(cls, json):
        return cls(
              get_all_game = json.get('a_get_all_game', False)
            , get_inactive_game = json.get('a_get_inactive_game', False)
            , game_ids = json.get('a_game_ids', '')
            , require_all_id_filters_met = json.get('a_require_all_id_filters_met', True)
            , require_any_id_filters_met = json.get('a_require_any_id_filters_met', True)
        )

    def to_json(self):
        return {
              'a_get_all_game': self.get_all_game
            , 'a_get_inactive_game': self.get_inactive_game
            , 'a_game_ids': self.game_ids
            , 'a_require_all_id_filters_met': self.require_all_id_filters_met
            , 'a_require_any_id_filters_met': self.require_any_id_filters_met
        }

    @staticmethod
    def get_type_hints():
        return {
              'a_get_all_game': Boolean
            , 'a_get_inactive_game': Boolean
            , 'a_game_ids': Text
            , 'a_require_all_id_filters_met': Boolean
            , 'a_require_any_id_filters_met': Boolean
        }
