package itemprops

import "github.com/shopspring/decimal"

type ItemPhysics struct {
	Material `json:"material"`
	//DimensionItemRigidity жёсткость (самого предмета а не материала), мера прочности,
	//уменьшается со временем, может зависеть от тепмературы
	DimensionItemRigidity    `json:"rigidity"`
	DimensionItemSize        `json:"size"`
	DimensionItemTemperature `json:"temperature"`
	//CubeFactor фактор близости куб <-> сфера по площади поверхности, чем ближе к 0, тем ближе к сфере,
	//100 - куб, >100 - для суперсложных (шипастых например) поверхностей
	CubeFactor decimal.NullDecimal `json:"cube_factor,omitempty"`
}

// DimensionItemSize length in m (1 mm = 1/1000 of 1m)
type DimensionItemSize struct {
	Width  decimal.Decimal `json:"width"`
	Height decimal.Decimal `json:"height"`
	// if item is solid - depth in m (1mm = 1/1000 of m)
	Depth decimal.NullDecimal `json:"depth,omitempty"`
	//Thickness if item is hollow - thickness of outer item shell, ie for armor, in m (1 mm = 1/1000 of m)
	Thickness decimal.NullDecimal `json:"thickness,omitempty"`
}

// Area is frontal area
func (d *DimensionItemSize) Area() decimal.Decimal {
	return d.Width.Mul(d.Height)
}

func (ip *ItemPhysics) Weight() decimal.Decimal {
	return ip.Material.Density.Mul(ip.Volume())
}

func (d *ItemPhysics) Volume() decimal.Decimal {
	v := d.Width.Mul(d.Height)
	//есть глубина
	if !d.Depth.Decimal.IsZero() {
		v = v.Mul(d.Depth.Decimal)
		//пустотелый
		if !d.Thickness.Decimal.IsZero() {
			surfaceArea := d.Width.Mul(d.Height).Mul(decimal.NewFromInt(2)).
				Add(d.Height.Mul(d.Depth.Decimal).Mul(decimal.NewFromInt(2))).
				Add(d.Width.Mul(d.Depth.Decimal).Mul(decimal.NewFromInt(2)))
			surfaceAreaCoeff := 0.85
			if !d.CubeFactor.Decimal.IsZero() {
				surfaceAreaCoeff = surfaceAreaCoeff * float64(int(d.CubeFactor.Decimal.IntPart())/100)
			}
			v = surfaceArea.Mul(d.Thickness.Decimal).
				//волюнтаристский коэффт отличия поверхности от куба, см https/en.wikipedia.org/wiki/Volume-to-surface_area_ratio
				Mul(decimal.NewFromFloat(surfaceAreaCoeff))
		}
	}
	return v
}
