package main

import (
	"encoding/json"
	"time"
)

type AttendanceState = int

const (
	出勤 = iota
	请假
	出差
	外出
	缺卡
	加班
	休息
	调班
)

const (
	年假 = iota
	调休
)

const (
	小时 = iota
	天
)

type EmailSetting struct {
	Id             string //ID
	Host           string //邮件服务器地址
	Port           string //端口
	Sender         string //发送者账号
	SenderPassword string //发送者密码
}

type DomainSetting struct {
	Id     string //ID
	Domain string //域名
}

type ViewCode struct {
	Id                      string    //Code Id
	Code                    string    //Code内容
	Receiver                string    //接收者
	WorkingDayStatisticsIds []string  //统计ID列表
	ExpiredTime             time.Time //Code 过期时间
}

func (viewCode ViewCode) MarshalJSON() ([]byte, error) {
	type Alias ViewCode
	return json.Marshal(&struct {
		Alias
		ExpiredTime string `json:"ExpiredTime"`
	}{Alias: Alias(viewCode), ExpiredTime: dateTimeToStr(viewCode.ExpiredTime)})
}

func (viewCode *ViewCode) UnmarshalJSON(data []byte) (err error) {
	type Alias ViewCode
	temp := new(struct {
		Alias
		ExpiredTime string `json:"ExpiredTime"`
	})
	err = json.Unmarshal(data, temp)
	if err == nil {
		viewCode.Id = temp.Id
		viewCode.Code = temp.Code
		viewCode.Receiver = temp.Receiver
		viewCode.WorkingDayStatisticsIds = make([]string, len(temp.WorkingDayStatisticsIds))
		copy(viewCode.WorkingDayStatisticsIds, temp.WorkingDayStatisticsIds)
		viewCode.ExpiredTime = strToDateTime(temp.ExpiredTime)
	}
	return err
}

type Admin struct {
	Id       string //管理员ID
	Name     string //管理员名
	Password string //管理员密码
}

type HolidayInfo struct {
	Id              string    //调休日ID
	Title           string    //调休日标题
	Holiday         time.Time //被调休日
	IsAdjusted      bool      //是否调班
	IsNationalLegal bool      //是否国家法定
	AdjustedDay     time.Time //调整到哪天上班
}

func (holidayInfo HolidayInfo) MarshalJSON() ([]byte, error) {
	type Alias HolidayInfo
	return json.Marshal(&struct {
		Alias
		Holiday     string `json:"Holiday"`
		AdjustedDay string `json:"AdjustedDay"`
	}{Alias: Alias(holidayInfo), Holiday: dateTimeToStr(holidayInfo.Holiday), AdjustedDay: dateTimeToStr(holidayInfo.AdjustedDay)})
}

func (holidayInfo *HolidayInfo) UnmarshalJSON(data []byte) (err error) {
	type Alias HolidayInfo
	temp := new(struct {
		Alias
		Holiday     string `json:"Holiday"`
		AdjustedDay string `json:"AdjustedDay"`
	})
	err = json.Unmarshal(data, temp)
	if err == nil {
		holidayInfo.Id = temp.Id
		holidayInfo.Title = temp.Title
		holidayInfo.Holiday = strToDateTime(temp.Holiday)
		holidayInfo.IsAdjusted = temp.IsAdjusted
		holidayInfo.IsNationalLegal = temp.IsNationalLegal
		holidayInfo.AdjustedDay = strToDateTime(temp.AdjustedDay)
	}
	return err
}

type AttendanceRules struct {
	Title string    //班次名
	Start time.Time //班次开始时间
	End   time.Time //班次结束时间
}

func (attendanceRules AttendanceRules) MarshalJSON() ([]byte, error) {
	type Alias AttendanceRules
	return json.Marshal(&struct {
		Alias
		Start string `json:"Start"`
		End   string `json:"End"`
	}{Alias: Alias(attendanceRules), Start: dateTimeToStr(attendanceRules.Start), End: dateTimeToStr(attendanceRules.End)})
}

func (attendanceRules *AttendanceRules) UnmarshalJSON(data []byte) (err error) {
	type Alias AttendanceRules
	temp := new(struct {
		Alias
		Start string `json:"Start"`
		End   string `json:"End"`
	})
	err = json.Unmarshal(data, temp)
	if err == nil {
		attendanceRules.Title = temp.Title
		attendanceRules.Start = strToDateTime(temp.Start)
		attendanceRules.End = strToDateTime(temp.End)
	}
	return err
}

type Department struct {
	Id       int    //部门ID
	Name     string //部门名
	ParentId int    //上级部门ID
}

type Employee struct {
	Id              string          //员工ID
	Name            string          //员工名
	Title           string          //职位
	DepartmentId    int             //部门Id
	Email           string          //电子邮箱
	AttendanceRules AttendanceRules //考勤班次
	IsReviewer      bool            //是否审核人员
	IsStruggle      bool            //是否参加奋斗计划
}

// AttendanceData From 钉钉
type AttendanceData struct {
	EmployeeId  string
	Day         time.Time
	Start       string
	End         string
	StartTime   time.Time
	EndTime     time.Time
	StartResult string
	EndResult   string
	Approve     string
	State       AttendanceState
}

type WorkingDayInfo struct {
	Id                    string          //工作日记录ID
	StatisticsId          string          //统计表ID
	EmployeeId            string          //员工ID
	Day                   time.Time       //日期
	Start                 time.Time       //上班时间
	StartResult           string          //开始说明
	End                   time.Time       //下班时间
	EndResult             string          //结束说明
	RequiredWorkingHours  float64         //当天需要工作的标准时间
	WorkingHours          float64         //实际工作小时数
	IsHoliday             bool            //是否节假日
	HolidayAdjusted       bool            //节假日已调整
	HolidayName           string          //节假日名
	AdjustedDay           time.Time       //调整日期，如果是调班的
	IsWeekend             bool            //是否是周末
	State                 AttendanceState //出勤状态
	ObtainedUnits         int             //加班的单位数，以2.5为单位
	AdjustedObtainedUnits int             //调整过的加班单位数
	AdjustDescription     string          //调整说明
	Adjusted              bool            //是否调整过
}

func (workingDayInfo WorkingDayInfo) MarshalJSON() ([]byte, error) {
	type Alias WorkingDayInfo
	return json.Marshal(&struct {
		Alias
		Day         string `json:"Day"`
		Start       string `json:"Start"`
		End         string `json:"End"`
		AdjustedDay string `json:"AdjustedDay"`
	}{Alias: Alias(workingDayInfo), Day: dateTimeToStr(workingDayInfo.Day), Start: dateTimeToStr(workingDayInfo.Start), End: dateTimeToStr(workingDayInfo.End), AdjustedDay: dateTimeToStr(workingDayInfo.AdjustedDay)})
}

func (workingDayInfo *WorkingDayInfo) UnmarshalJSON(data []byte) (err error) {
	type Alias WorkingDayInfo
	temp := new(struct {
		Alias
		Day         string `json:"Day"`
		Start       string `json:"Start"`
		End         string `json:"End"`
		AdjustedDay string `json:"AdjustedDay"`
	})
	err = json.Unmarshal(data, temp)
	if err == nil {
		workingDayInfo.Id = temp.Id
		workingDayInfo.StatisticsId = temp.StatisticsId
		workingDayInfo.EmployeeId = temp.EmployeeId
		workingDayInfo.Day = dateTimeToDate(strToDateTime(temp.Day))
		workingDayInfo.Start = dateTimeToTime(strToDateTime(temp.Start))
		workingDayInfo.StartResult = temp.StartResult
		workingDayInfo.End = dateTimeToTime(strToDateTime(temp.End))
		workingDayInfo.EndResult = temp.EndResult
		workingDayInfo.RequiredWorkingHours = temp.RequiredWorkingHours
		workingDayInfo.WorkingHours = temp.WorkingHours
		workingDayInfo.IsHoliday = temp.IsHoliday
		workingDayInfo.HolidayName = temp.HolidayName
		workingDayInfo.HolidayAdjusted = temp.HolidayAdjusted
		workingDayInfo.AdjustedDay = dateTimeToDate(strToDateTime(temp.AdjustedDay))
		workingDayInfo.IsWeekend = temp.IsWeekend
		workingDayInfo.State = temp.State
		workingDayInfo.ObtainedUnits = temp.ObtainedUnits
		workingDayInfo.AdjustedObtainedUnits = temp.AdjustedObtainedUnits
		workingDayInfo.AdjustDescription = temp.AdjustDescription
		workingDayInfo.Adjusted = temp.Adjusted
	}
	return err
}

type WorkingDayStatistics struct {
	Id                   string
	Employee             Employee  //员工信息
	DepartmentId         int       //部门ID
	DepartmentName       string    //部门名
	Start                time.Time //开始时间
	End                  time.Time //结束时间
	RequiredReachedCount int       //需达标次数
	ReachedCount         int       //达标次数
	AdjustedReachedCount int       //调整后增加的次数
	Adjusted             bool      //是否已经调整过
	AdjustDescription    string    //调整说明
	AdjustedBy           string    //调整人
	Comment              string    //备注
	Reviewer             string    //审核人
}

func (workingDayStatistics WorkingDayStatistics) MarshalJSON() ([]byte, error) {
	type Alias WorkingDayStatistics
	return json.Marshal(&struct {
		Alias
		Start string `json:"Start"`
		End   string `json:"End"`
	}{Alias: Alias(workingDayStatistics), Start: dateTimeToStr(workingDayStatistics.Start), End: dateTimeToStr(workingDayStatistics.End)})
}

func (workingDayStatistics *WorkingDayStatistics) UnmarshalJSON(data []byte) (err error) {
	type Alias WorkingDayStatistics
	temp := new(struct {
		Alias
		Start string `json:"Start"`
		End   string `json:"End"`
	})
	err = json.Unmarshal(data, temp)
	if err == nil {
		workingDayStatistics.Id = temp.Id
		workingDayStatistics.Employee = temp.Employee
		workingDayStatistics.DepartmentId = temp.DepartmentId
		workingDayStatistics.DepartmentName = temp.DepartmentName
		workingDayStatistics.Start = strToDateTime(temp.Start)
		workingDayStatistics.End = strToDateTime(temp.End)
		workingDayStatistics.RequiredReachedCount = temp.RequiredReachedCount
		workingDayStatistics.ReachedCount = temp.ReachedCount
		workingDayStatistics.AdjustedReachedCount = temp.AdjustedReachedCount
		workingDayStatistics.Adjusted = temp.Adjusted
		workingDayStatistics.AdjustDescription = temp.AdjustDescription
		workingDayStatistics.AdjustedBy = temp.AdjustedBy
		workingDayStatistics.Comment = temp.Comment
		workingDayStatistics.Reviewer = temp.Reviewer
	}
	return err
}

type StatisticsTable struct {
	Id                      string    //工作统计集合ID
	Title                   string    //工作统计集合名称
	RequiredReachedCount    int       //需达标的次数
	WorkingDayStatisticsIds []string  //工作统计ID集合
	CreateTime              time.Time //创建时间
}

func (workingDayStatisticsCollection StatisticsTable) MarshalJSON() ([]byte, error) {
	type Alias StatisticsTable
	return json.Marshal(&struct {
		Alias
		CreateTime string `json:"CreateTime"`
	}{Alias: Alias(workingDayStatisticsCollection), CreateTime: dateTimeToStr(workingDayStatisticsCollection.CreateTime)})
}

func (workingDayStatisticsCollection *StatisticsTable) UnmarshalJSON(data []byte) (err error) {
	type Alias StatisticsTable
	temp := new(struct {
		Alias
		CreateTime string `json:"CreateTime"`
	})
	err = json.Unmarshal(data, temp)
	if err == nil {
		workingDayStatisticsCollection.Id = temp.Id
		workingDayStatisticsCollection.Title = temp.Title
		workingDayStatisticsCollection.RequiredReachedCount = temp.RequiredReachedCount
		workingDayStatisticsCollection.WorkingDayStatisticsIds = temp.WorkingDayStatisticsIds
		workingDayStatisticsCollection.CreateTime = strToDateTime(temp.CreateTime)
	}
	return err
}

type CheckHistory struct {
	CheckDay   time.Time //查询时间
	TotalUnits int       //当前达标次数
}

type MessageTemplate struct {
	Id      string //模板ID
	Name    string //模板名
	Content string //模板内容
}

type LeaveQuota struct {
	Id        string //员工ID
	LeaveType string //假期类型
	Unit      int    //单位
	Quota     int    //余额
	Used      int    //已使用
}

type DashBoardItem struct {
	Id       string //ID
	ItemName string //数据类型
	Data     int    //数值
}
