import { AbilityAccessors } from '../Ability';
import { FormatUtils } from '../Format';
import { getEntityId, getFriendlySubtypeName, getPrerequisites, getSubType, getType, getValue, getShouldExclude, } from './accessors';
import { PrerequisiteSubTypeEnum, PrerequisiteTypeEnum } from './constants';
import { validatePrerequisite } from './validators';
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailure(prerequisite, prerequisiteData) {
    switch (getType(prerequisite)) {
        case PrerequisiteTypeEnum.ABILITY_SCORE:
            return getPrerequisiteFailureAbilityScore(prerequisite, prerequisiteData);
        case PrerequisiteTypeEnum.PROFICIENCY:
            return getPrerequisiteFailureProficiency(prerequisite);
        case PrerequisiteTypeEnum.SPECIES:
            return getPrerequisiteFailureRace(prerequisite);
        case PrerequisiteTypeEnum.SIZE:
            return getPrerequisiteFailureSize(prerequisite);
        case PrerequisiteTypeEnum.SPECIES_OPTION:
            return getPrerequisiteFailureSubrace(prerequisite);
        case PrerequisiteTypeEnum.LEVEL:
            return getPrerequisiteFailureLevel(prerequisite);
        case PrerequisiteTypeEnum.CLASS:
            return getPrerequisiteFailureClass(prerequisite);
        case PrerequisiteTypeEnum.FEAT:
            return getPrerequisiteFailureFeat(prerequisite);
        case PrerequisiteTypeEnum.CLASS_FEATURE:
            return getPrerequisiteFailureClassFeature(prerequisite);
        case PrerequisiteTypeEnum.CUSTOM_VALUE:
        default:
        // not defined
    }
    return null;
}
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailureLevel(prerequisite) {
    let requiredDescription = '';
    switch (getSubType(prerequisite)) {
        case PrerequisiteSubTypeEnum.CHARACTER_LEVEL:
            let value = getValue(prerequisite);
            value = value ? value : 1;
            requiredDescription = `${FormatUtils.ordinalize(value)} Level`;
            break;
        default:
        // not implemented
    }
    return {
        type: PrerequisiteTypeEnum.LEVEL,
        data: {
            requiredChoice: getFriendlySubtypeName(prerequisite),
            requiredDescription,
        },
        shouldExclude: !!getShouldExclude(prerequisite),
    };
}
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailureAbilityScore(prerequisite, prerequisiteData) {
    let statKey = '';
    let currentAmount = null;
    const entityId = getEntityId(prerequisite);
    if (entityId !== null) {
        const ability = prerequisiteData.abilityLookup[entityId];
        statKey = AbilityAccessors.getStatKey(ability);
        currentAmount = AbilityAccessors.getScore(ability);
    }
    return {
        type: PrerequisiteTypeEnum.ABILITY_SCORE,
        data: {
            statKey,
            currentAmount,
            requiredValue: getValue(prerequisite),
            requiredChoice: getFriendlySubtypeName(prerequisite),
            requiredDescription: `${getFriendlySubtypeName(prerequisite)} ${getValue(prerequisite)}+`,
        },
        shouldExclude: !!getShouldExclude(prerequisite),
    };
}
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailureProficiency(prerequisite) {
    return {
        type: PrerequisiteTypeEnum.PROFICIENCY,
        data: {
            requiredChoice: getFriendlySubtypeName(prerequisite),
            requiredDescription: `${getFriendlySubtypeName(prerequisite)} Proficiency`,
        },
        shouldExclude: !!getShouldExclude(prerequisite),
    };
}
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailureRace(prerequisite) {
    return {
        type: PrerequisiteTypeEnum.SPECIES,
        data: {
            requiredChoice: getFriendlySubtypeName(prerequisite),
            requiredDescription: getFriendlySubtypeName(prerequisite),
        },
        shouldExclude: !!getShouldExclude(prerequisite),
    };
}
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailureSubrace(prerequisite) {
    return {
        type: PrerequisiteTypeEnum.SPECIES_OPTION,
        data: {
            requiredChoice: getFriendlySubtypeName(prerequisite),
            requiredDescription: getFriendlySubtypeName(prerequisite),
        },
        shouldExclude: !!getShouldExclude(prerequisite),
    };
}
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailureSize(prerequisite) {
    return {
        type: PrerequisiteTypeEnum.SIZE,
        data: {
            requiredChoice: getFriendlySubtypeName(prerequisite),
            requiredDescription: `${getFriendlySubtypeName(prerequisite)} Size`,
        },
        shouldExclude: !!getShouldExclude(prerequisite),
    };
}
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailureClass(prerequisite) {
    return {
        type: PrerequisiteTypeEnum.CLASS,
        data: {
            requiredChoice: getFriendlySubtypeName(prerequisite),
            requiredDescription: `${getFriendlySubtypeName(prerequisite)}`,
        },
        shouldExclude: !!getShouldExclude(prerequisite),
    };
}
export const getPrerequisiteFailureClassFeature = (prerequisite) => ({
    type: PrerequisiteTypeEnum.CLASS_FEATURE,
    data: {
        requiredChoice: prerequisite.friendlySubTypeName,
        requiredDescription: prerequisite.friendlySubTypeName,
    },
    shouldExclude: !!getShouldExclude(prerequisite),
});
/**
 *
 * @param prerequisite
 * @param prerequisiteData
 */
export function getPrerequisiteFailureFeat(prerequisite) {
    return {
        type: PrerequisiteTypeEnum.FEAT,
        data: {
            requiredChoice: getFriendlySubtypeName(prerequisite),
            requiredDescription: `${getFriendlySubtypeName(prerequisite)}`,
        },
        shouldExclude: !!getShouldExclude(prerequisite),
    };
}
/**
 *
 * @param prerequisiteGrouping
 * @param prerequisiteData
 */
export function getPrerequisiteGroupingFailures(prerequisiteGrouping, prerequisiteData) {
    const groupingFailures = [];
    if (prerequisiteGrouping !== null) {
        prerequisiteGrouping.forEach((prerequisiteGroup) => {
            const groupFailures = [];
            const prerequisites = getPrerequisites(prerequisiteGroup);
            prerequisites.forEach((prerequisite) => {
                if (!validatePrerequisite(prerequisite, prerequisiteData)) {
                    const prereqFailure = getPrerequisiteFailure(prerequisite, prerequisiteData);
                    if (prereqFailure) {
                        groupFailures.push(prereqFailure);
                    }
                }
            });
            groupingFailures.push(groupFailures);
        });
    }
    return groupingFailures.filter((group) => group.length);
}
