use enum_dispatch::enum_dispatch;

use crate::{
  card::{Card, Cards},
  character::CharacterSkill,
  dice::ActualDices,
  effect::target::StaticTarget,
  element::Element,
};

pub enum ActionType {
  SelectCards,
  SelectActiveCharacter,
  SelectDices,
  PlayCard,
  CastSkill,
  SwapCharacter,
  ElementalTuning,
  EndRound,
}

#[enum_dispatch(PlayerActionTrait)]
pub enum PlayerAction {
  CardsSelectAction,
  DicesSelectAction,
  CharacterSelectAction,
  EndRoundAction,
}

#[enum_dispatch]
pub trait PlayerActionTrait {}

pub struct CardsSelectAction {
  pub cards: Cards,
}

pub struct DicesSelectAction {
  pub dices: ActualDices,
}

pub struct CharacterSelectAction {
  pub character: usize,
}

pub struct EndRoundAction;

#[enum_dispatch(GameActionTrait)]
pub enum GameAction {
  ElementalTuningAction,
  CardAction,
  SkillAction,
  SwapAction,
  DeathSwapAction,
}

#[enum_dispatch]
pub trait GameActionTrait {}

pub struct ElementalTuningAction {
  pub card: Card,
  pub elem: Element,
}

pub struct CardAction {
  pub card: Card,
  pub instruction: Instruction,
}

pub struct SkillAction {
  pub character_skill: CharacterSkill,
  pub instruction: DiceOnlyInstruction,
}

pub struct SwapAction {
  pub character: usize,
  pub instruction: Instruction,
}

pub struct DeathSwapAction {
  pub character: usize,
}

#[enum_dispatch(InstructionTrait)]
pub enum Instruction {
  DiceOnlyInstruction,
  StaticTargetInstruction,
  SourceTargetInstruction,
}

#[enum_dispatch]
pub trait InstructionTrait {}

pub struct DiceOnlyInstruction {}

pub struct StaticTargetInstruction {
  pub target: StaticTarget,
}

pub struct SourceTargetInstruction {
  pub source: StaticTarget,
  pub target: StaticTarget,
}