package comm

import (
	"math"
	"time"

	"go.mongodb.org/mongo-driver/bson/primitive"
)

type MaterailUv struct {
	Scale   float32 `bson:"scale" json:"scale"`
	Rotate  float32 `bson:"rotate" json:"rotate"`
	OffsetX float32 `bson:"offsetX" json:"offsetX"`
	OffsetY float32 `bson:"offsetY" json:"offsetY"`
}

type MaterialConf struct {
	MatId     primitive.ObjectID `bson:"matId,omitempty" json:"matId"` //材质球Id
	Thumbnail *OssType           `bson:"thumbnail,omitempty" json:"thumbnail"`
	Name      string             `bson:"name,omitempty" json:"name"`
	CusNum    string             `bson:"cusNum,omitempty" json:"cusNum"` //编号

	NormalMap      *OssType `bson:"normalMap,omitempty" json:"normalMap"`
	DisplaceMap    *OssType `bson:"displaceMap,omitempty" json:"displaceMap"` //置换贴图
	DisplaceFactor *float64 `bson:"displaceFactor,omitempty" json:"displaceFactor"`
	BaseMap        *OssType `bson:"baseMap,omitempty" json:"baseMap"`
	BaseColor      *Vect3   `bson:"baseColor,omitempty" json:"baseColor"`
	RoughMap       *OssType `bson:"roughMap,omitempty" json:"roughMap"`
	RoughFactor    *float64 `bson:"roughFactor,omitempty" json:"roughFactor"`
	MetalMap       *OssType `bson:"metalMap,omitempty" json:"metalMap"`
	MetalFactor    *float64 `bson:"metalFactor,omitempty" json:"metalFactor"`

	DiffuseMap   *OssType `bson:"diffuseMap,omitempty" json:"diffuseMap"`
	DiffuseColor *Vect3   `bson:"diffuseColor,omitempty" json:"diffuseColor"`
	GlossMap     *OssType `bson:"glossMap,omitempty" json:"glossMap"` //光泽贴图
	GlossFactor  *float64 `bson:"glossFactor,omitempty" json:"glossFactor"`
	SpecMap      *OssType `bson:"specMap,omitempty" json:"specMap"`     //高光贴图
	SpecColor    *Vect3   `bson:"specColor,omitempty" json:"specColor"` //高光贴图

	OpacMap    *OssType `bson:"opacMap,omitempty" json:"opacMap"`       //透明度
	OpacFactor *float64 `bson:"opacFactor,omitempty" json:"opacFactor"` //透明度贴图

	Type string `bson:"type,omitempty" json:"type"` //spec meta  //高光流 金属流(默认)

	Uvtransform *MaterailUv `bson:"uv,omitempty" json:"uv"`

	CusUvTransform *MaterailUv `bson:"cusUv,omitempty" json:"cusUv"`         //用户定义的uv
	LogicType      string      `bson:"logicType,omitempty" json:"logicType"` //fabric3d fabric2d color //3d面料 2d图片面料 color //特殊材质球
	UserData       interface{} `bson:"userData,omitempty" json:"userData"`   //指定要数据放置的字段
}

type SpecialMat struct {
	Id        primitive.ObjectID `bson:"_id,omitempty" json:"_id"` //材质球Id
	Thumbnail *OssType           `bson:"thumbnail,omitempty" json:"thumbnail"`
	Name      string             `bson:"name,omitempty" json:"name"`

	NormalMap      *OssType `bson:"normalMap,omitempty" json:"normalMap"`
	DisplaceMap    *OssType `bson:"displaceMap,omitempty" json:"displaceMap"` //置换贴图
	DisplaceFactor *float64 `bson:"displaceFactor,omitempty" json:"displaceFactor"`
	BaseMap        *OssType `bson:"baseMap,omitempty" json:"baseMap"`
	BaseColor      *Vect3   `bson:"baseColor,omitempty" json:"baseColor"`
	RoughMap       *OssType `bson:"roughMap,omitempty" json:"roughMap"`
	RoughFactor    *float64 `bson:"roughFactor,omitempty" json:"roughFactor"`
	MetalMap       *OssType `bson:"metalMap,omitempty" json:"metalMap"`
	MetalFactor    *float64 `bson:"metalFactor,omitempty" json:"metalFactor"`

	DiffuseMap   *OssType `bson:"diffuseMap,omitempty" json:"diffuseMap"`
	DiffuseColor *Vect3   `bson:"diffuseColor,omitempty" json:"diffuseColor"`
	GlossMap     *OssType `bson:"glossMap,omitempty" json:"glossMap"` //光泽贴图
	GlossFactor  *float64 `bson:"glossFactor,omitempty" json:"glossFactor"`
	SpecMap      *OssType `bson:"specMap,omitempty" json:"specMap"`     //高光贴图
	SpecColor    *Vect3   `bson:"specColor,omitempty" json:"specColor"` //高光贴图

	OpacMap    *OssType `bson:"opacMap,omitempty" json:"opacMap"`       //透明度
	OpacFactor *float64 `bson:"OpacFactor,omitempty" json:"OpacFactor"` //透明度贴图

	Type string `bson:"type,omitempty" json:"type"` //spec meta  //高光流 金属流(默认)

	Category string `bson:"category,omitempty" json:"category"`

	Uvtransform *MaterailUv `bson:"uv,omitempty" json:"uv"`

	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
}

type LineMat struct {
	Id        primitive.ObjectID `bson:"_id,omitempty" json:"_id"` //材质球Id
	Thumbnail *OssType           `bson:"thumbnail,omitempty" json:"thumbnail"`
	Name      string             `bson:"name,omitempty" json:"name"`

	NormalMap      *OssType `bson:"normalMap,omitempty" json:"normalMap"`
	DisplaceMap    *OssType `bson:"displaceMap,omitempty" json:"displaceMap"` //置换贴图
	DisplaceFactor *float64 `bson:"displaceFactor,omitempty" json:"displaceFactor"`
	BaseMap        *OssType `bson:"baseMap,omitempty" json:"baseMap"`
	BaseColor      *Vect3   `bson:"baseColor,omitempty" json:"baseColor"`
	RoughMap       *OssType `bson:"roughMap,omitempty" json:"roughMap"`
	RoughFactor    *float64 `bson:"roughFactor,omitempty" json:"roughFactor"`
	MetalMap       *OssType `bson:"metalMap,omitempty" json:"metalMap"`
	MetalFactor    *float64 `bson:"metalFactor,omitempty" json:"metalFactor"`

	DiffuseMap   *OssType `bson:"diffuseMap,omitempty" json:"diffuseMap"`
	DiffuseColor *Vect3   `bson:"diffuseColor,omitempty" json:"diffuseColor"`
	GlossMap     *OssType `bson:"glossMap,omitempty" json:"glossMap"` //光泽贴图
	GlossFactor  *float64 `bson:"glossFactor,omitempty" json:"glossFactor"`
	SpecMap      *OssType `bson:"specMap,omitempty" json:"specMap"`     //高光贴图
	SpecColor    *Vect3   `bson:"specColor,omitempty" json:"specColor"` //高光贴图

	OpacMap    *OssType `bson:"opacMap,omitempty" json:"opacMap"`       //透明度
	OpacFactor *float64 `bson:"OpacFactor,omitempty" json:"OpacFactor"` //透明度贴图

	Type string `bson:"type,omitempty" json:"type"` //spec meta  //高光流 金属流(默认)

	Category string `bson:"category,omitempty" json:"category"`

	Uvtransform *MaterailUv `bson:"uv,omitempty" json:"uv"`

	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
}

func (m *SpecialMat) Copy2MaterialConf() *MaterialConf {
	return &MaterialConf{
		MatId:          m.Id,
		Thumbnail:      m.Thumbnail,
		Name:           m.Name,
		NormalMap:      m.NormalMap,
		DisplaceMap:    m.DiffuseMap,
		DisplaceFactor: m.DisplaceFactor,
		BaseMap:        m.BaseMap,
		BaseColor:      m.BaseColor,
		RoughMap:       m.RoughMap,
		RoughFactor:    m.RoughFactor,
		MetalMap:       m.MetalMap,
		MetalFactor:    m.MetalFactor,
		DiffuseMap:     m.DiffuseMap,
		DiffuseColor:   m.DiffuseColor,
		GlossMap:       m.GlossMap,
		GlossFactor:    m.GlossFactor,
		SpecMap:        m.SpecMap,
		SpecColor:      m.SpecColor,
		OpacMap:        m.OpacMap,
		OpacFactor:     m.OpacFactor,
		Type:           m.Type,
		Uvtransform:    m.Uvtransform,
	}
}

const MIN = 0.0001

// MIN 为用户自定义的比较精度
func IsEqualFloat32(f1, f2 float32) bool {
	return math.Dim(float64(f1), float64(f2)) < MIN
}
func IsEqualFloat64(f1, f2 float64) bool {
	return math.Dim(f1, f2) < MIN
}

func IsEqualboolp(b1p, b2p *bool) bool {
	b1 := false
	b2 := false
	if b1p != nil {
		b1 = *b1p
	}
	if b2p != nil {
		b2 = *b2p
	}
	return b1 == b2
}

func IsEqualFloat64p(f1p, f2p *float64) bool {
	f1 := 0.0
	f2 := 0.0
	if f1p != nil {
		f1 = *f1p
	}
	if f2p != nil {
		f2 = *f2p
	}
	return math.Dim(f1, f2) < MIN
}

func (mat *MaterialConf) IsEqual(mat2 *MaterialConf) bool {
	changed := false
	if mat.BaseMap == nil || mat2.BaseMap == nil {
		changed = changed || mat.BaseMap != mat2.BaseMap
	} else {
		changed = changed || (*mat.BaseMap).Url != (*mat2.BaseMap).Url
	}

	if mat.NormalMap == nil || mat2.NormalMap == nil {
		changed = changed || mat.NormalMap != mat2.NormalMap
	} else {
		changed = changed || (*mat.NormalMap).Url != (*mat2.NormalMap).Url
	}
	if mat.RoughMap == nil || mat2.RoughMap == nil {
		changed = changed || mat.RoughMap != mat2.RoughMap
	} else {
		changed = changed || (*mat.RoughMap).Url != (*mat2.RoughMap).Url
	}

	if mat.SpecMap == nil || mat2.SpecMap == nil {
		changed = changed || mat.SpecMap != mat2.SpecMap
	} else {
		changed = changed || (*mat.SpecMap).Url != (*mat2.SpecMap).Url
	}

	changed = changed || !IsEqualFloat64p(mat.RoughFactor, mat2.RoughFactor)
	changed = changed || !IsEqualFloat64p(mat.MetalFactor, mat2.MetalFactor)

	if mat.MetalMap == nil || mat2.MetalMap == nil {
		changed = changed || mat.MetalMap != mat2.MetalMap
	} else {
		changed = changed || (*mat.MetalMap).Url != (*mat2.MetalMap).Url
	}
	if changed {
		return false
	}

	if mat.Uvtransform == nil || mat2.Uvtransform == nil {
		changed = mat2.Uvtransform == nil
	} else {
		changed = changed || !IsEqualFloat32(mat.Uvtransform.OffsetX, mat2.Uvtransform.OffsetX) ||
			!IsEqualFloat32(mat.Uvtransform.Scale, mat2.Uvtransform.Scale) ||
			!IsEqualFloat32(mat.Uvtransform.Rotate, mat2.Uvtransform.Rotate)
	}
	return !changed
}