package vqdcms

import (
	"database/sql/driver"
	"easyvqd/internal/core/vqd"
	"encoding/json"
	"time"
)

const VQD_IMAGES_DIR = "snap"

type Abnormal struct {
	Value float32 `json:"value"`
	Name  string  `json:"name"`
}

type abnormal []Abnormal

func (r *abnormal) Scan(val interface{}) error {
	b, _ := val.([]byte)
	return json.Unmarshal(b, r)
}

func (r abnormal) Value() (driver.Value, error) {
	return json.Marshal(r)
}

type DefaultValue struct {
	Thr1  float32 `json:"thr1"`
	Name1 string  `json:"name1"`
	Thr2  float32 `json:"thr2"`
	Name2 string  `json:"name2"`
	Ratio float32 `json:"ratio"` //比例
}

type defaultValue []DefaultValue

func (r *defaultValue) Scan(val interface{}) error {
	b, _ := val.([]byte)
	return json.Unmarshal(b, r)
}

func (r defaultValue) Value() (driver.Value, error) {
	return json.Marshal(r)
}

type AbnormalModel struct {
	ID            int          `gorm:"primary_key" json:"id"`
	TaskName      string       `json:"task_name"`
	ChannelID     string       `json:"channel_id"`
	ChannelName   string       `json:"channel_name"`
	PlanID        int          `json:"plan_id"`
	PlanName      string       `json:"plan_name"`
	TemplateID    int          `json:"template_id"`
	TemplateName  string       `json:"template_name"`
	FilePath      string       `json:"file_path"`
	IsDeep        bool         `json:"is_deep"`
	Abnormals     abnormal     `gorm:"type:json" json:"abnormals"`
	DefaultValues defaultValue `gorm:"type:json" json:"default_values"` //设置的默认阈值
	CreatedAt     time.Time    `json:"created_at"`
	UpdatedAt     time.Time    `json:"updated_at"`
}

/* 偏色参数 */
type VQDColorPara struct {
	ColorThr float32 /* 偏色判断值,*/

	/* 偏色次数比例,
	   默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */
	ColorAbnNumRatio float32

	Resverd1 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3 float32 /* 保留,暂时不设置,默认 -999  */
}

/* 亮暗参数 */
// OK
type VQDLgtDarkPara struct {
	/* 超过200的像素比例,过亮阈值,
	   默认 0.1, 取值范围: 0~1, 建议范围: 0.1~0.5,
	   值设置的越大, 越不灵敏, 就是非常亮才算过亮
	   值设置的越小, 越灵敏, 太小的话误报会很多 */
	LightThr float32

	/* 低于55的像素比例,过暗阈值,
	   默认 0.4, 取值范围: 0~1, 建议范围: 0.2~0.6
	   值设置的越大, 越不灵敏, 就是非常暗才算过暗
	   值设置的越小, 越灵敏, 太小的话误报会很多 */
	DarkThr float32

	/* 偏暗或者偏亮次数比例, 连续多次检测出现的次数比例
	   默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */
	LgtDarkAbnNumRatio float32

	Resverd1 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3 float32 /* 保留,暂时不设置,默认 -999 */
}

/* 清晰度参数 */
// OK
type VQDClarityPara struct {
	/* 清晰度判断阈值, 小于该值判定为模糊,
	   默认为0.4, 取值范围: 0~1, 建议范围: 0.3~0.99
	   值设置的越大, 越不灵敏, 太大的话误报模糊会很多
	   值设置的越小, 就是非常模糊才算模糊 */
	ClarityThr float32

	/* 清晰度异常次数比例,
	   默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */
	ClarityAbnNumRatio float32

	Resverd1 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3 float32 /* 保留,暂时不设置,默认 -999 */
}

/* 噪声参数 */
type VQDNoisePara struct {
	NoiseThr float32 /* 噪声判断阈值,默认为 35 */

	/* 噪声次数比例,
	   默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */
	NoiseAbnNumRatio float32
	Resverd1         float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2         float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3         float32 /* 保留,暂时不设置,默认 -999 */
}

/* 对比度参数 */
type VQDContrastPara struct {
	CtraLowThr  float32 /* 低对比度判断阈值,默认为 30 */
	CtraHighThr float32 /* 高对比度判断阈值,默认为 120 */

	/* 对比度异常次数比例,
	   默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */
	CtraAbnNumRatio float32
	Resverd1        float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2        float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3        float32 /* 保留,暂时不设置,默认 -999 */
}

/* 遮挡参数 */
type VQDOcclusionPara struct {
	OcclusionThr float32 /* 遮挡判断阈值,默认为 6 */

	/* 遮挡次数比例
	   默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */
	OcclusionAbnNumRatio float32
	Resverd1             float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2             float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3             float32 /* 保留,暂时不设置,默认 -999 */
}

/* 蓝屏参数 */
// OK
type VQDBluePara struct {
	/* 蓝屏判断阈值, 蓝色像素占图像面积比例,
	   默认为 0.6, 取值范围: 0~1, 建议范围 0.4~0.9  */
	BlueThr float32

	/* 蓝屏次数比例, 连续多帧中蓝色占比
	   默认为0.5, 取值范围: 0~1, 建议范围: 0.1~0.9 */
	BlueAbnNumRatio float32
	Resverd1        float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2        float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3        float32 /* 保留,暂时不设置,默认 -999 */
}

/* 抖动参数, 做抖动检测, 尽量隔帧取帧做,  */
// OK
type VQDSharkPara struct {
	/* 抖动阈值参数
	   全局运动均值, 无论是目标移动还是画面抖动, 全局运动均值相对来讲都会比较大,
	   默认为 0.2, 取值范围: 0~10, 建议范围: 0.1~0.8 */
	SharkThr float32

	/* 出现抖动次数的比例,
	   默认为0.2, 取值范围: 0~1, 建议范围: 0.1~0.6 */
	SharkAbnNumRatio float32

	/* 全局运动幅度方差阈值, 理论上来讲, 抖动为全局画面移动, 方向幅度具有一致性, 方差应较小
	   默认为0.2, 取值范围: 0~1, 建议范围: 0.05~0.5
	   如果内部有很多运动目标, 该值较大, 所以设置较大, 会使得在有运动目标时, 判定为抖动 */
	Resverd1 float32

	/* 全局运动方向方差阈值, 小于该值时, 判定为全局运动, 可能会抖动
	   默认为0.2, 取值范围: 0~1, 建议范围: 0.05~0.5
	   如果内部有很多运动目标, 该值较大, 所以设置较大, 会使得在有运动目标时, 判定为抖动 */
	Resverd2 float32
	Resverd3 float32 /* 保留,暂时不设置,默认 -999 */
}

/* 冻结参数 */
// OK
type VQDFreezePara struct {
	/* 冻结阈值参数
	   静止的像素比例, 默认为0.999, 取值范围: 0.8~1, 建议范围: 0.99~1
	   如果画面静止, 该值比较大, 甚至会接近于1, */
	FreezeThr float32 /* 冻结阈值 */

	/* 冻结帧数占得比例, 尽量设置的大一些, 避免那些无运动目标的静止监控画面
	   默认为0.99, 取值范围: 0.8~1, 建议范围: 0.95~1, */
	FreezeAbnNumRatio float32
	Resverd1          float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2          float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3          float32 /* 保留,暂时不设置,默认 -999 */
}

/*
马赛克检测

	NEW: 新增深度学习版本 2.0.0
*/
type VQDMosaicPara struct {
	/* 马赛克阈值参数
	   NEW: 新增深度学习版本 20240717
	       默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9,
	       大于该值判定为偏色, 小于该值判定为正常,
	*/
	MosaicThr float32

	/* 马赛克次数比例, 连续多帧中马赛克占比
	   默认为0.5,取值范围: 0~1, 建议范围: 0.3
	   连续多帧中马赛克占比 */
	MosaicAbnNumRatio float32

	Resverd1 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3 float32 /* 保留,暂时不设置,默认 -999 */
}

/*
花屏检测 NEW NEW NEW NEW NEW

	NEW: 新增深度学习版本 2.0.0
*/
type VQDFlowerPara struct {
	/* 花屏阈值参数
	   NEW: 新增深度学习版本 20240717
	       默认为 0.1 取值范围: 0~1, 建议范围: 0.1~0.9,
	       大于该值判定为偏色, 小于该值判定为正常,
	*/
	FlowerThr float32

	/* 花屏次数比例, 连续多帧中花屏占比
	   默认为0.5, 取值范围: 0~1, 建议范围: 0.3
	   连续多帧中花屏占比 */
	FlowerAbnNumRatio float32

	Resverd1 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd2 float32 /* 保留,暂时不设置,默认 -999 */
	Resverd3 float32 /* 保留,暂时不设置,默认 -999 */
}

type VQDPara struct {
	VecFrmNum       int              /* 连续分析帧数(2-64), 默认为10, 最大为 64 */
	UseDeepLearning bool             /* 是否使用深度学习版本, 默认使用深度学习版本 NEW: 20240717 */
	EnableFunc      int              /* 功能使能,默认为 NXU_VQD_ENABLE_ALL,多项功能用或 */
	ColorPara       VQDColorPara     /* 偏色参数 */
	LgtDarkPara     VQDLgtDarkPara   /* 亮暗参数 */
	ClarityPara     VQDClarityPara   /* 清晰度参数 */
	NoisePara       VQDNoisePara     /* 噪声参数 */
	ContrastPara    VQDContrastPara  /* 对比度参数 */
	OcclusionPara   VQDOcclusionPara /* 遮挡参数 */
	BluePara        VQDBluePara      /* 蓝屏参数 */
	SharkPara       VQDSharkPara     /* 抖动参数 */
	FreezePara      VQDFreezePara    /* 冻结参数 */

	MosaicPara VQDMosaicPara /* 马赛克检测 */
	FlowerPara VQDFlowerPara /* 花屏检测 */
}

// config
func NewVQDPara(tem *vqd.VqdTaskTemplate) VQDPara {
	var strFunc []string
	if tem.VqdConfig.Enable {
		strFunc = append(strFunc, "vqd_config")
	}
	if tem.VqdLgtDark.Enable {
		strFunc = append(strFunc, "vqd_lgt_dark")
	}
	if tem.VqdBlue.Enable {
		strFunc = append(strFunc, "vqd_blue")
	}
	if tem.VqdClarity.Enable {
		strFunc = append(strFunc, "vqd_clarity")
	}
	if tem.VqdShark.Enable {
		strFunc = append(strFunc, "vqd_shark")
	}
	if tem.VqdFreeze.Enable {
		strFunc = append(strFunc, "vqd_freeze")
	}
	if tem.VqdColor.Enable {
		strFunc = append(strFunc, "vqd_color")
	}
	if tem.VqdOcclusion.Enable {
		strFunc = append(strFunc, "vqd_occlusion")
	}
	if tem.VqdNoise.Enable {
		strFunc = append(strFunc, "vqd_noise")
	}
	if tem.VqdContrast.Enable {
		strFunc = append(strFunc, "vqd_contrast")
	}
	if tem.VqdMosaic.Enable {
		strFunc = append(strFunc, "vqd_mosaic")
	}
	if tem.VqdFlower.Enable {
		strFunc = append(strFunc, "vqd_flower")
	}
	EnableFunc := GetAlgoEnable(strFunc)
	return VQDPara{
		VecFrmNum:       int(tem.VqdConfig.FrmNum),
		UseDeepLearning: tem.VqdConfig.IsDeepLearn,
		EnableFunc:      EnableFunc,
		ColorPara: VQDColorPara{
			ColorThr:         tem.VqdColor.ColorThr,
			ColorAbnNumRatio: tem.VqdColor.ColorAbnNumRatio,
		},
		LgtDarkPara: VQDLgtDarkPara{
			LightThr:           tem.VqdLgtDark.LgtThr,
			DarkThr:            tem.VqdLgtDark.DarkThr,
			LgtDarkAbnNumRatio: tem.VqdLgtDark.LgtDarkAbnNumRatio,
		},
		ClarityPara: VQDClarityPara{
			ClarityThr:         tem.VqdClarity.ClarityThr,
			ClarityAbnNumRatio: tem.VqdClarity.ClarityAbnNumRatio,
		},
		NoisePara: VQDNoisePara{
			NoiseThr:         tem.VqdNoise.NoiseThr,
			NoiseAbnNumRatio: tem.VqdNoise.NoiseAbnNumRatio,
		},
		ContrastPara: VQDContrastPara{
			CtraLowThr:      tem.VqdContrast.CtraLowThr,
			CtraHighThr:     tem.VqdContrast.CtraHighThr,
			CtraAbnNumRatio: tem.VqdContrast.CtraAbnNumRatio,
		},
		OcclusionPara: VQDOcclusionPara{
			OcclusionThr:         tem.VqdOcclusion.OcclusionThr,
			OcclusionAbnNumRatio: tem.VqdOcclusion.OcclusionAbnNumRatio,
		},
		BluePara: VQDBluePara{
			BlueThr:         tem.VqdBlue.BlueThr,
			BlueAbnNumRatio: tem.VqdBlue.BlueAbnNumRatio,
		},
		SharkPara: VQDSharkPara{
			SharkThr:         tem.VqdShark.SharkThr,
			SharkAbnNumRatio: tem.VqdShark.SharkAbnNumRatio,
		},
		FreezePara: VQDFreezePara{
			FreezeThr:         tem.VqdFreeze.FreezeThr,
			FreezeAbnNumRatio: tem.VqdFreeze.FreezeAbnNumRatio,
		},
		MosaicPara: VQDMosaicPara{
			MosaicThr:         tem.VqdMosaic.MosaicThr,
			MosaicAbnNumRatio: tem.VqdMosaic.MosaicAbnNumRatio,
		},
		FlowerPara: VQDFlowerPara{
			FlowerThr:         tem.VqdFlower.FlowerThr,
			FlowerAbnNumRatio: tem.VqdFlower.FlowerAbnNumRatio,
		},
	}
}

/*
异常结果

	当前各异常返回出来的值,作为参考,外面也可以存到列表中进行应用
*/
type VQDResult struct {
	AbnormalType int     /* 异常类型,多种类型的,利用与或来确定异常类型 */
	ColorDev     float32 /* 偏色检测 */
	LgtDark      float32 /* 亮暗检测 */
	Clarity      float32 /* 清晰度检测 */
	Noise        float32 /* 噪声检测 */
	Contrast     float32 /* 对比度检测 */
	Occlusion    float32 /* 遮挡检测 */
	Blue         float32 /* 蓝屏检测 */
	Shark        float32 /* 抖动检测 */
	Freeze       float32 /* 冻结检测 */
	Mosaic       float32 /* 马赛克检测 NEW: 新增深度学习版本 2.0.0*/
	Flower       float32 /* 花屏检测 NEW: 新增深度学习版本 2.0.0*/
	Resverd1     int     /* 保留,暂时不设置,默认 -999 */
	Resverd2     int     /* 保留,暂时不设置,默认 -999 */
	Resverd3     int     /* 保留,暂时不设置,默认 -999 */
}
