package host

import (
	"database/sql/driver"
	"encoding"
	"encoding/json"
	"fmt"
	"strings"

	"git.lnton.com/lnton/pkg/orm"
	"github.com/lib/pq"
	"gorm.io/gorm"
)

// Channel 通道
type Channel struct {
	ID           string         `gorm:"primaryKey;column:id" json:"id"` // ID
	CreatedAt    orm.Time       `gorm:"type:timestamptz;notNull;default:CURRENT_TIMESTAMP;index;comment:创建时间" json:"created_at"`
	UpdatedAt    orm.Time       `gorm:"type:timestamptz;notNull;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"`
	Enabled      bool           `gorm:"column:enabled;notNull;default:true;comment:是否启用" json:"enabled"`         // 是否启用
	Name         string         `gorm:"column:name;notNull;default:'';comment:通道名称" json:"name"`                 // 通道名称
	DeviceID     string         `gorm:"column:device_id;notNull;default:'';index;comment:设备ID" json:"device_id"` // 设备 id
	Protocol     string         `gorm:"column:protocol;notNull;default:'';comment:通道协议" json:"protocol"`         // 通道协议
	PTZType      int            `gorm:"column:ptz_type;notNull;default:0;comment:云台类型" json:"ptz_type"`          // 云台类型
	Remark       string         `gorm:"column:remark;notNull;default:'';comment:备注" json:"remark"`               // 备注描述
	Transport    string         `gorm:"column:transport;notNull;default:'TCP';comment:传输协议" json:"transport"`    // TCP/UDP
	IP           string         `gorm:"column:ip;notNull;default:'';comment:IP" json:"ip"`                       // ip 地址
	Port         int            `gorm:"column:port;notNull;default:0;comment:端口号" json:"port"`                   // 端口号
	Username     string         `gorm:"column:username;notNull;default:'';comment:用户名" json:"-"`                 // 用户名
	Password     string         `gorm:"column:password;notNull;default:'';comment:密码" json:"-"`                  // 密码
	BID          string         `gorm:"column:bid;notNull;default:'';comment:协议专属 id" json:"bid"`
	PTZ          bool           `gorm:"column:ptz;notNull;default:FALSE;comment:是否支持 ptz" json:"ptz"` // 是否支持 ptz
	Talk         bool           `gorm:"column:talk;notNull;default:FALSE;comment:是否支持对讲" json:"talk"` // 是否支持语音对讲
	PID          string         `gorm:"column:pid;notNull;index;default:'';comment:父通道 ID" json:"pid"`
	Groups       pq.StringArray `gorm:"column:groups;type:text[];default:'{}';comment:虚拟组织" json:"-"`
	Ext          ChannelExt     `gorm:"column:ext;type:jsonb;notNull;default:'{}';comment:扩展字段" json:"ext"`
	ChildCount   int            `gorm:"column:child_count;notNull;default:0" json:"child_count"` // 子通道数量(不包含子孙通道)
	Status       bool           `gorm:"column:status;notNull;default:false;comment:通道状态" json:"status"`
	LastPushedAt orm.Time       `gorm:"column:last_pushed_at;notNull;index;default:'1970-01-01 00:00:00';comment:最后推送时间" json:"last_pushed_at"`
	// CustomGBID   string         `gorm:"column:custom_gb_id;notNull;default:'';comment:自定义国标ID" json:"custom_gb_id"`
	DefaultGBID string `gorm:"column:default_gb_id;notNull;default:'';comment:默认国标ID" json:"default_gb_id"` // 默认国标ID
	CustomName  string `gorm:"column:custom_name;notNull;default:'';comment:自定义名称 " json:"custom_name"`

	URL                 string `gorm:"-" json:"url"`     //
	Playing             bool   `gorm:"-" json:"playing"` // 是否播放中
	PlayingStatus       string `gorm:"-" json:"playing_status"`
	IsDir               bool   `gorm:"-" json:"is_dir"`                // 是否目录
	RecordPlanEnabled   bool   `gorm:"-" json:"record_plan_enabled"`   // 是否启用了录像计划
	CascadeShareEnabled bool   `gorm:"-" json:"cascade_share_enabled"` // 是否启用了级联共享
	CustomID            string `gorm:"-" json:"custom_id"`
	IsRecording         bool   `gorm:"-" json:"is_recording"` // 是否配置录像计划
	PlanID              int    `gorm:"-" json:"plan_id"`      // 绑定的录像计划
	DeviceName          string `gorm:"-" json:"device_name"`  // 设备名称;单独给前端用的

	// 长沙地铁项目
	ServerID   string `gorm:"column:server_id;notNull;default:'';comment:平台ID" json:"server_id" `
	ServerName string `json:"column:server_name;notNull;default:'';comment:平台名称" json:"server_name"`

	// Latitude  float32
	// Longitude float32
}

func (a ChannelExt) Value() (driver.Value, error) {
	return json.Marshal(a)
}

func (c *Channel) GetTransport() string {
	switch strings.ToUpper(c.Transport) {
	case "UDP":
		return "UDP"
	case "TCPA":
		return "TCPA"
	default:
		return "TCP"
	}
}

func (d *Channel) BeforeCreate(tx *gorm.DB) error {
	d.CreatedAt = orm.Now()
	d.UpdatedAt = orm.Now()
	return nil
}

func (d *Channel) BeforeUpdate(tx *gorm.DB) error {
	d.UpdatedAt = orm.Now()
	return nil
}

// type sortByChannel []*device.SyncReply_Channel

// func (a sortByChannel) Len() int           { return len(a) }
// func (a sortByChannel) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
// func (a sortByChannel) Less(i, j int) bool { return a[i].GetBid() < a[j].GetBid() }

// ChannelExt 通道的扩展内容，主要集中在国标上
type ChannelExt struct {
	Parental int    `json:"parental"`  // 是否有子设备(1:有;0:没有)
	ParentID string `json:"parent_id"` // 父设备/区域/系统ID
}

// SetIsDir 设置是否为目录
func (i *Channel) SetIsDir() {
	i.IsDir = i.ChildCount > 0 || i.Ext.Parental == 1
}

// Scan implements orm.Scaner.
func (i *ChannelExt) Scan(input interface{}) error {
	return orm.JsonUnmarshal(input, i)
}

// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (c *Channel) UnmarshalBinary(data []byte) error {
	return orm.JsonUnmarshal(data, c)
}

// MarshalBinary implements encoding.BinaryMarshaler.
func (c *Channel) MarshalBinary() (data []byte, err error) {
	return json.Marshal(c)
}

var (
	_ encoding.BinaryMarshaler   = (*Channel)(nil)
	_ encoding.BinaryUnmarshaler = (*Channel)(nil)
)

// GetID 根据不同的设备类型返回 id
// func (c *Channel) GetID() string {
// 	switch c.Protocol {
// 	case DeviceTypeSD, DeviceTypeGB, DeviceTypeOnvif, DeviceTypePull:
// 		return c.BID
// 	}
// 	return c.ID
// }

// GetBID 获取设备BID
// BID是通道的实际ID
// GB28181: 由设备提供20位纯数字
// ONVIF: 由设备提供可能带有下划线
// PULL: 由平台提供，例如: 01,02(目前只支持单通道)
func (c *Channel) GetBID() string {
	// switch c.Protocol {
	// case DeviceTypeSD, DeviceTypeGB, DeviceTypeOnvif, DeviceTypePull,DeviceTypePush:
	// 	return c.BID
	// }
	// return c.ID
	return c.BID
}

// GetStreamName 获取流 id
func (c *Channel) GetStreamName() string {
	return fmt.Sprintf("%s_%s", c.DeviceID, c.GetBID())
}

// TableName 指定表名
// func (Channel) TableName() string {
// 	return "channels"
// }
//
// // IsGB28181 ...
// func (c Channel) IsGB28181() bool {
// 	return c.Protocol == DeviceTypeGB
// }
//
// // IsSaida ...
// func (c Channel) IsSaida() bool {
// 	return c.Protocol == DeviceTypeSD
// }
//
// // IsSupportLocalRecord 该协议是否支持本地录像
// func (c *Channel) IsSupportLocalRecord() bool {
// 	return c.Protocol == DeviceTypeSD
// }
