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

Technology: Backend
Feature:    MTG Game Form

Description:
Defines Flask-WTF form for handling user input on MTG Games page.
"""

# IMPORTS
# internal
from business_objects.base import Base
from business_objects.tcg.mtg_game import MTG_Game, Parameters_MTG_Game
from business_objects.tcg.mtg_game_player import MTG_Game_Player, Parameters_MTG_Game_Player
from business_objects.tcg.mtg_game_round import MTG_Game_Round, Parameters_MTG_Game_Round
from business_objects.tcg.mtg_game_round_player_damage import Parameters_MTG_Game_Round_Player_Damage
from business_objects.tcg.mtg_deck import MTG_Deck, Parameters_MTG_Deck
from helpers.helper_app import Helper_App
from forms.base import Form_Base
import lib.argument_validation as av
# external
from flask import Flask, render_template, request, flash, redirect, url_for, current_app
from flask_wtf import FlaskForm
from wtforms import SelectField, BooleanField, StringField, SubmitField, DateField
from wtforms.validators import DataRequired, Email, ValidationError, Optional
import markupsafe
from abc import ABCMeta, abstractmethod
import json


class Filters_MTG_Game(Form_Base):
    search = StringField(
        'Search'
    )
    active_only = BooleanField(
          'Active'
        , default=True
    )
    is_commander = BooleanField(
          'Commander'
        , default=False
    )
    is_draft = BooleanField(
          'Draft'
        , default=False
    )
    is_sealed = BooleanField(
          'Sealed'
        , default=False
    )
    date_from = DateField(
          'From Date'
        , validators=[Optional()]
    )
    date_to = DateField(
          'To Date'
        , validators=[Optional()]
    )

    @classmethod
    def from_json(cls, json):
        _m = f'{cls.__qualname__}.from_json'
        # Helper_App.console_log(f'{_m}\njson: {json}')
        filters = cls()
        filters.search.data = json.get(Base.FLAG_SEARCH, '')
        filters.active_only.data = av.input_bool(json.get(Base.FLAG_ACTIVE_ONLY, True), Base.FLAG_ACTIVE_ONLY, _m)
        filters.is_commander.data = av.input_bool(json.get(MTG_Game.FLAG_IS_COMMANDER, False), MTG_Game.FLAG_IS_COMMANDER, _m)
        filters.is_draft.data = av.input_bool(json.get(MTG_Game.FLAG_IS_DRAFT, False), MTG_Game.FLAG_IS_DRAFT, _m)
        filters.is_sealed.data = av.input_bool(json.get(MTG_Game.FLAG_IS_SEALED, False), MTG_Game.FLAG_IS_SEALED, _m)
        filters.date_from.data = json.get(Base.FLAG_DATE_FROM, None)
        filters.date_to.data = json.get(Base.FLAG_DATE_TO, None)
        return filters

    def to_json(self):
        return {
              Base.FLAG_SEARCH: self.search.data
            , Base.FLAG_ACTIVE_ONLY: self.active_only.data
            , MTG_Game.FLAG_IS_COMMANDER: self.is_commander.data
            , MTG_Game.FLAG_IS_DRAFT: self.is_draft.data
            , MTG_Game.FLAG_IS_SEALED: self.is_sealed.data
            , Base.FLAG_DATE_FROM: self.date_from.data
            , Base.FLAG_DATE_TO: self.date_to.data
        }

    def to_parameters(self, user_id_session):
        return Parameters_MTG_Game (
              get_all_game = True
            , get_inactive_game = not self.active_only.data
            , game_ids = ''
            , get_all_user = False
            , get_inactive_user = False
            , user_ids = '' if user_id_session is None else str(user_id_session)
            , require_all_id_filters_met = True
            , require_any_id_filters_met = True
            , require_all_non_id_filters_met = False
            , require_any_non_id_filters_met = True
        )


class Filters_MTG_Game_Player(Form_Base):
    search = StringField(
        'Search'
    )
    active_only = BooleanField(
          'Active'
        , default=True
    )

    @classmethod
    def from_json(cls, json):
        _m = f'{cls.__qualname__}.from_json'
        # Helper_App.console_log(f'{_m}\njson: {json}')
        filters = cls()
        filters.search.data = json.get(Base.FLAG_SEARCH, '')
        filters.active_only.data = av.input_bool(json.get(Base.FLAG_ACTIVE_ONLY, True), Base.FLAG_ACTIVE_ONLY, _m)
        return filters

    def to_json(self):
        return {
              Base.FLAG_SEARCH: self.search.data
            , Base.FLAG_ACTIVE_ONLY: self.active_only.data
        }

    def to_parameters(self, user_id_session, game_id=None):
        params = Parameters_MTG_Game_Player(
              get_all_player = True
            , get_inactive_player = not self.active_only.data
            , player_ids = ''
            , game_ids = str(game_id) if game_id else ''
            , user_ids = str(user_id_session) if user_id_session else ''
            , deck_ids = ''
            , require_all_id_filters_met = True
            , require_any_id_filters_met = True
            , require_all_non_id_filters_met = False
            , require_any_non_id_filters_met = True
        )
        return params


class Filters_MTG_Deck(Form_Base):
    search = StringField(
        'Search'
    )
    active_only = BooleanField(
          'Active'
        , default=True
    )
    is_commander = BooleanField(
          'Commander'
        , default=False
    )

    @classmethod
    def from_json(cls, json):
        _m = f'{cls.__qualname__}.from_json'
        # Helper_App.console_log(f'{_m}\njson: {json}')
        filters = cls()
        filters.search.data = json.get(Base.FLAG_SEARCH, '')
        filters.active_only.data = av.input_bool(json.get(Base.FLAG_ACTIVE_ONLY, True), Base.FLAG_ACTIVE_ONLY, _m)
        filters.is_commander.data = av.input_bool(json.get(MTG_Deck.FLAG_IS_COMMANDER, False), MTG_Deck.FLAG_IS_COMMANDER, _m)
        return filters

    def to_json(self):
        return {
              Base.FLAG_SEARCH: self.search.data
            , Base.FLAG_ACTIVE_ONLY: self.active_only.data
            , MTG_Deck.FLAG_IS_COMMANDER: self.is_commander.data
        }

    def to_parameters(self):
        return Parameters_MTG_Deck(
              get_all_deck = True
            , get_inactive_deck = not self.active_only.data
            , deck_ids = ''
            , deck_names = self.search.data
            , include_commander_option = True
            , commander_bracket_ids = ''
            , require_all_id_filters_met = False
            , require_any_id_filters_met = True
            , require_all_non_id_filters_met = False
            , require_any_non_id_filters_met = True
        )
