import React from "react";

import {
  CharacterTheme,
  Constants,
  DataOriginRefData,
  EntityUtils,
  FormatUtils,
  RuleData,
  Spell,
  SpellUtils,
} from "@dndbeyond/character-rules-engine/es";

import { Accordion } from "~/components/Accordion";
import { SpellName } from "~/components/SpellName";

import SpellDetail from "../../SpellDetail";
import styles from "./styles.module.css";

export class SpellListItem extends React.PureComponent<
  {
    spell: Spell;
    castAsRitual: boolean;
    footerNode?: any;
    spellCasterInfo: any;
    ruleData: RuleData;
    dataOriginRefData: DataOriginRefData;
    proficiencyBonus: number;
    theme: CharacterTheme;
  },
  {
    customizeCollapsed: boolean;
  }
> {
  static defaultProps = {
    castAsRitual: false,
  };

  constructor(props) {
    super(props);

    this.state = {
      customizeCollapsed: true,
    };
  }

  getActions = () => {
    const { spell, ruleData } = this.props;
    const { toHit, attackSaveValue } = spell;
    const requiresAttackRoll = SpellUtils.getRequiresAttackRoll(spell);
    const requiresSavingThrow = SpellUtils.getRequiresSavingThrow(spell);

    if (requiresAttackRoll && toHit !== null) {
      return (
        <p className={styles.callout}>
          <span>To Hit</span>
          <span>{FormatUtils.renderSignedNumber(toHit)}</span>
        </p>
      );
    }

    if (requiresSavingThrow) {
      return (
        <p className={styles.callout}>
          <span>{SpellUtils.getSaveDcAbilityKey(spell, ruleData)}</span>
          <span>{attackSaveValue}</span>
        </p>
      );
    }
  };

  getMetaItems = () => {
    const { spell, dataOriginRefData } = this.props;
    const level = SpellUtils.getLevel(spell);
    const concentration = SpellUtils.getConcentration(spell);
    const rangeArea = SpellUtils.getDefinitionRangeArea(spell);
    const attackType = SpellUtils.getAttackType(spell);

    let metaItems: Array<string> = [];
    metaItems.push(FormatUtils.renderSpellLevelName(level));
    let expandedDataOriginRef = SpellUtils.getExpandedDataOriginRef(spell);
    if (expandedDataOriginRef !== null)
      metaItems.push(
        EntityUtils.getDataOriginRefName(
          expandedDataOriginRef,
          dataOriginRefData
        )
      );
    if (concentration) metaItems.push("Concentration");
    if (rangeArea)
      metaItems.push(
        attackType && attackType === Constants.AttackTypeRangeEnum.RANGED
          ? `Range ${rangeArea}`
          : rangeArea
      );

    return metaItems;
  };

  render() {
    const { customizeCollapsed } = this.state;
    const {
      spell,
      castAsRitual,
      footerNode,
      spellCasterInfo,
      ruleData,
      proficiencyBonus,
      theme,
    } = this.props;

    let clsNames = ["attack-list-customize-header"];
    if (customizeCollapsed) {
      clsNames.push("attack-list-customize-header-closed");
    } else {
      clsNames.push("attack-list-customize-header-opened");
    }
    const school = SpellUtils.getSchool(spell);
    const spellImage = `https://www.dndbeyond.com/Content/Skins/Waterdeep/images/spell-schools/35/${school?.toLowerCase()}.png`;

    return (
      <Accordion
        className={styles.spell}
        summary={
          <SpellName
            spell={spell}
            showSpellLevel={false}
            showLegacyBadge={true}
          />
        }
        summaryAction={this.getActions()}
        summaryImage={spellImage}
        summaryImageAlt={`Icon for the ${school} school of magic`}
        summaryMetaItems={this.getMetaItems()}
        variant="paper"
      >
        <SpellDetail
          theme={theme}
          spell={spell}
          castAsRitual={castAsRitual}
          spellCasterInfo={spellCasterInfo}
          enableCaster={false}
          ruleData={ruleData}
          showCustomize={false}
          showActions={false}
          proficiencyBonus={proficiencyBonus}
        />
        {footerNode}
      </Accordion>
    );
  }
}

export default class SpellList extends React.PureComponent<{
  spells: Array<Spell>;
  hideRemaining: boolean;
  castAsRitual: boolean;
  spellCasterInfo: any;
  ruleData: RuleData;
  dataOriginRefData: DataOriginRefData;
  proficiencyBonus: number;
  theme: CharacterTheme;
}> {
  static defaultProps = {
    hideRemaining: false,
    castAsRitual: false,
  };

  render() {
    const {
      spells,
      castAsRitual,
      spellCasterInfo,
      ruleData,
      dataOriginRefData,
      proficiencyBonus,
      theme,
    } = this.props;

    if (!spells.length) {
      return null;
    }

    return (
      <div className="spell-list">
        <div className="spell-list-items">
          {spells.map((spell) => (
            <SpellListItem
              theme={theme}
              spell={spell}
              key={`${spell.id}-${SpellUtils.getId(spell)}`}
              castAsRitual={castAsRitual}
              spellCasterInfo={spellCasterInfo}
              ruleData={ruleData}
              dataOriginRefData={dataOriginRefData}
              proficiencyBonus={proficiencyBonus}
            />
          ))}
        </div>
      </div>
    );
  }
}
