package bx

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"time"
)

type CmdSystemClockCorrect struct {
	baseBxCmd
	sysTime                                      time.Time
	year, month, day, hour, minute, second, week int
}

func NewBxCmdSystemClockCorrect(t time.Time) CmdSystemClockCorrect {
	fmt.Println(t.Year())
	fmt.Println(t.Month())
	fmt.Println(t.Day())
	fmt.Println(t.Hour())
	fmt.Println(t.Minute())
	fmt.Println(t.Second())
	fmt.Println(t.Weekday())
	year, _ := BIN2Uint64(Uint2BCD(uint64(t.Year()), false), binary.LittleEndian)
	month, _ := BIN2Uint64(Uint2BCD(uint64(t.Month()), false), binary.LittleEndian)
	day, _ := BIN2Uint64(Uint2BCD(uint64(t.Day()), false), binary.LittleEndian)
	hour, _ := BIN2Uint64(Uint2BCD(uint64(t.Hour()), false), binary.LittleEndian)
	minute, _ := BIN2Uint64(Uint2BCD(uint64(t.Minute()), false), binary.LittleEndian)
	second, _ := BIN2Uint64(Uint2BCD(uint64(t.Second()), false), binary.LittleEndian)
	week, _ := BIN2Uint64(Uint2BCD(uint64(t.Weekday()), false), binary.LittleEndian)
	if week == 0 {
		week = 7
	}
	return CmdSystemClockCorrect{
		baseBxCmd: newBaseCmd(CMD_SYSTEM_CLOCK_CORRECT.group, CMD_SYSTEM_CLOCK_CORRECT.code),
		sysTime:   t,
		year:      int(year),
		month:     int(month),
		day:       int(day),
		hour:      int(hour),
		minute:    int(minute),
		second:    int(second),
		week:      int(week),
	}
}

// uint转BCD
func Uint2BCD(n uint64, isBigEndian bool) []byte {
	var b []byte
	//if n < 256 {
	//	b = []byte{0}
	//}
	for i := 0; ; i++ {
		h := (n / 10) % 10
		l := n % 10
		b = append(b, byte(h<<4|l))
		n = n / 100
		if n == 0 {
			break
		}
	}
	if !isBigEndian {
		return b
	}
	l := len(b)
	var r = make([]byte, l)
	for i, v := range b {
		r[l-1-i] = v
	}
	return r
}
func BIN2Uint64(bin []byte, order binary.ByteOrder) (uint64, error) {
	len := len(bin)
	switch len {
	case 1:
		return uint64(bin[0]), nil
	case 2:
		return uint64(order.Uint16(bin)), nil
	case 3, 4:
		bin4 := make([]byte, 8)
		copy(bin4[4-len:], bin) //前面字节填充0
		return uint64(order.Uint32(bin4)), nil
	case 5, 6, 7, 8:
		bin8 := make([]byte, 8)
		copy(bin8[8-len:], bin)
		return order.Uint64(bin8), nil
	default:
		return 0, errors.New("不符合字节长度范围1-8")
	}
}

func (this CmdSystemClockCorrect) Build() []byte {
	w := bytes.NewBuffer(make([]byte, 0, 1024))
	binary.Write(w, binary.LittleEndian, this.Group())
	binary.Write(w, binary.LittleEndian, this.Cmd())
	binary.Write(w, binary.LittleEndian, this.ReqResp())
	binary.Write(w, binary.LittleEndian, byte(0x00))
	binary.Write(w, binary.LittleEndian, byte(0x00))
	//BCD码：年（2）+月（1）+日（1）+时（1）+分（1）+秒（1）+星期（1）；先地位再高位
	//年：低端发送，低位在前
	y := []byte{
		byte(this.year),
		byte(this.year >> 8),
		byte(this.year >> 16),
		byte(this.year >> 24),
	}
	if y[0] == 0x00 && y[1] == 0x00 {
		binary.Write(w, binary.LittleEndian, y[2])
		binary.Write(w, binary.LittleEndian, y[3])
	} else {
		binary.Write(w, binary.LittleEndian, y[0])
		binary.Write(w, binary.LittleEndian, y[1])
	}
	//月
	m := []byte{
		byte(this.month),
		byte(this.month >> 8),
		byte(this.month >> 16),
		byte(this.month >> 24),
	}
	binary.Write(w, binary.LittleEndian, m[0])
	d := []byte{
		byte(this.day),
		byte(this.day >> 8),
		byte(this.day >> 16),
		byte(this.day >> 24),
	}
	binary.Write(w, binary.LittleEndian, d[0])
	h := []byte{
		byte(this.hour),
		byte(this.hour >> 8),
		byte(this.hour >> 16),
		byte(this.hour >> 24),
	}
	binary.Write(w, binary.LittleEndian, h[0])
	min := []byte{
		byte(this.minute),
		byte(this.minute >> 8),
		byte(this.minute >> 16),
		byte(this.minute >> 24),
	}
	binary.Write(w, binary.LittleEndian, min[0])
	s := []byte{
		byte(this.second),
		byte(this.second >> 8),
		byte(this.second >> 16),
		byte(this.second >> 24),
	}
	binary.Write(w, binary.LittleEndian, s[0])
	week := []byte{
		byte(this.week),
		byte(this.week >> 8),
		byte(this.week >> 16),
		byte(this.week >> 24),
	}
	binary.Write(w, binary.LittleEndian, week[0])
	return w.Bytes()
}
