
export interface M5Skill {
	label: string
	skill: string
	attribute: string
	fw: number
	ew: number
}

export interface M5Attribute {
	value: number
	bonus: number
}

export interface M5CharacterCalculatedData {
	level: number,
	stats: {
		armor: number,
		defense: number,
		damageBonus: number,
		attackBonus: number,
		defenseBonus: number,
		movementBonus: number,
		resistanceMind: number,
		resistanceBody: number,
		spellCasting: number,
		brawl: number,
		poisonResistance: number,
		enduranceBonus: number
	},
	skills: {
	}
}

export default class M5Character extends Actor {

	// constructor(
	// 	data: ConstructorParameters<typeof foundry.documents.BaseActor>[0],
	// 	context?: ConstructorParameters<typeof foundry.documents.BaseActor>[1]
	// ) {
	// 	super(data, context)
	// 	this.prepareDerivedData()
	// }

	static attributeMinMax(attribute: M5Attribute) {
		return Math.min(100, Math.max(0, attribute.value + attribute.bonus))
	}

	static attributeBonus(attribute: M5Attribute) {
		const value = this.attributeMinMax(attribute)
		if (value > 95)
			return 2
		if (value > 80)
			return 1
		if (value > 20)
			return 0
		if (value > 5)
			return -1
		return -2
	}

	prepareDerivedData() {
		const context = (this as any).data;
		//console.log(context)

		context.data.calc = {
			level: 0,
			stats: {
				armor: 0,
				defense: 0,
				damageBonus: 0,
				attackBonus: 0,
				defenseBonus: 0,
				movementBonus: 0,
				resistanceMind: 0,
				resistanceBody: 0,
				spellCasting: 0,
				brawl: 0,
				poisonResistance: 0,
				enduranceBonus: 0
			},
			skills: {}
		} as M5CharacterCalculatedData

		const data = context.data
		const st = M5Character.attributeMinMax(data.attributes.st)
		const gs = M5Character.attributeMinMax(data.attributes.gs)
		const gw = M5Character.attributeMinMax(data.attributes.gw)
		const ko = M5Character.attributeMinMax(data.attributes.ko)

		const calc = context.data.calc as M5CharacterCalculatedData
		calc.level = M5Character.levelFromExp(data.es)
		calc.stats.armor = 0
		calc.stats.defense = M5Character.defenseFromLevel(calc.level)
		calc.stats.damageBonus = Math.floor(st/20) + Math.floor(gs/30) - 3
		calc.stats.attackBonus = M5Character.attributeBonus(data.attributes.gs)
		calc.stats.defenseBonus = M5Character.attributeBonus(data.attributes.gw)
		calc.stats.movementBonus = 0
		calc.stats.resistanceMind = calc.stats.defense
		calc.stats.resistanceBody = calc.stats.defense + 1
		calc.stats.spellCasting = M5Character.spellCastingFromLevel(calc.level) + M5Character.attributeBonus(data.attributes.zt)
		calc.stats.brawl = Math.floor((st + gw) / 20)
		calc.stats.poisonResistance = 30 + Math.floor(ko / 2)
		calc.stats.enduranceBonus = Math.floor(ko/10) + Math.floor(st/20)
	}

	static readonly levelThreshold: Array<number> = [0, 100, 250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 6000, 7000, 8000, 9000, 10000, 12500, 15000, 17500, 20000, 22500, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 65000, 70000, 75000, 80000, 85000, 90000, 95000, 100000, 105000, 110000, 115000, 120000, 125000, 130000, 135000, 140000, 145000, 150000, 155000, 160000, 165000, 170000, 175000, 180000, 185000, 190000, 195000, 200000, 205000, 210000, 215000, 220000, 225000, 230000, 235000, 240000, 245000, 250000, 255000, 260000, 265000, 270000, 275000, 280000]
	static levelFromExp(exp: number): number {
		const ret = M5Character.levelThreshold.findIndex(val => val > exp)
		return ret === -1 ? M5Character.levelThreshold.length : ret
	}

	static readonly defenseThreshold: Array<[number, number]> = [
		[1, 11],
		[2, 12],
		[5, 13],
		[10, 14],
		[15, 15],
		[20, 16],
		[25, 17],
		[30, 18]
	]
	static defenseFromLevel(lvl: number): number {
		const ret = M5Character.defenseThreshold.find(val => val[0] >= lvl)
		return ret ? ret[1] : M5Character.defenseThreshold[M5Character.defenseThreshold.length - 1][1]
	}

	static readonly spellCastingThreshold: Array<[number, number]> = [
		[1, 11],
		[2, 12],
		[4, 13],
		[6, 14],
		[8, 15],
		[10, 16],
		[15, 17],
		[20, 18]
	]
	static spellCastingFromLevel(lvl: number): number {
		const ret = M5Character.spellCastingThreshold.find(val => val[0] >= lvl)
		return ret ? ret[1] : M5Character.spellCastingThreshold[M5Character.spellCastingThreshold.length - 1][1]
	}

	attributeStrength() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.st)
	}

	attributeDexterity() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.gs)
	}

	attributeAgility() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.gw)
	}

	attributeConstitution() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.ko)
	}

	attributeIntelligence() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.in)
	}

	attributeMagic() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.zt)
	}

	attributeBeauty() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.au)
	}

	attributeCharisma() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.pa)
	}

	attributeWillpower() {
		const data = (this as any).data.data
		return M5Character.attributeMinMax(data.data.attributes.wk)
	}

}
