package common

import (
	"time"

	"github.com/fiskerinc/cloud-services/pkg/grpc/kafka_grpc"
)

// CANFrame provides struct for can bus messages
type CANFrame struct {
	TimestampUSec int    `json:"epoch_usec" parquet:"name=epoch_usec, type=INT64"`
	ID            int    `json:"id" parquet:"name=id, type=INT32"`
	Data          string `json:"data" parquet:"name=data, type=BYTE_ARRAY"`
}

type CANBusMessage struct {
	EpochUsec int        `json:"epoch_usec"`
	Dropped   int        `json:"dropped"`
	Filtered  int        `json:"filtered"`
	Frames    []CANFrame `json:"frames"`
}

// CANSignal provides struct for parsed can bus messages
type CANSignal struct {
	VIN         string  `json:"vin"`
	Timestamp   float64 `json:"timestamp" parquet:"name=timestamp, type=FLOAT"`
	ID          int     `json:"id" parquet:"name=id, type=INT32"`
	Name        string  `json:"name" parquet:"name=name, type=BYTE_ARRAY"`
	Value       float64 `json:"value" parquet:"name=value, type=FLOAT"`
	Description string  `json:"description,omitempty"`
}

type CANSignalExport struct {
	VIN              string    `json:"vin"`
	Timestamp        time.Time `json:"timestamp"`
	Name             string    `json:"name"`
	Value            float64   `json:"value"`
	TimestampInMilli int64     `json:"tm"`
}

// "missing destination name \"BCM_FrntDrDoorLockSts\" in *common.CANSignal"
type CANSignalQuery struct {
	VIN            string   `json:"vin" validate:"required"`
	TimestampStart float64  `json:"timestamp_start" validate:"required"`
	TimestampEnd   float64  `json:"timestamp_end" validate:"required"`
	Offset         int      `json:"offset"`
	Limit          int      `json:"limit"`
	SelectAll      bool     `json:"select_all"`
	CanSignals     []string `json:"can_signals"`
}

type ExportCANSignalQuery struct {
	VIN            string   `json:"vin" validate:"required"`
	TimestampStart int64    `json:"timestamp_start" validate:"required"`
	TimestampEnd   int64    `json:"timestamp_end" validate:"required"`
	Offset         int      `json:"offset"`
	Limit          int      `json:"limit"`
	SelectAll      bool     `json:"select_all"`
	CanSignals     []string `json:"can_signals"`
}

type CANSignalNameList struct {
	Signal_Name string `json:"signal_name"`
}

type CANSignalData struct {
	cansignals []CANSignal `json:"cansignals"`
}

type CANSignalBatchPayload struct {
	Data CANSignalData `json:"data"`
}

// CANFilter provides struct for filtering can messages based on ID
type CANFilter struct {
	CANID    string     `json:"can_id" bson:"can_id" validate:"required,can_id"`
	Interval *int       `json:"interval,omitempty" bson:"interval" validate:"omitempty,gte=0"`
	EdgeMask *BinaryHex `json:"edge_mask,omitempty" bson:"edge_mask,omitempty" validate:"omitempty,lte=10000"`
}

// CANFilterWithFleet is used only for rendering vehicle's fleets' filters.
type CANFilterWithFleet struct {
	CANID    string     `json:"can_id" bson:"can_id" validate:"required,can_id"`
	Interval *int       `json:"interval,omitempty" bson:"interval" validate:"gte=0"`
	Fleet    string     `json:"fleet,omitempty" bson:"fleet,omitempty"`
	EdgeMask *BinaryHex `json:"edge_mask,omitempty" bson:"edge_mask,omitempty" validate:"omitempty,lte=10000"`
}

func (c *CANSignalBatchPayload) ToGrpc(data []CANSignal) *kafka_grpc.GRPC_CANSignalBatchPayload {
	grpccansignals := make([]*kafka_grpc.GRPC_CANSignal, len(data))

	msg := kafka_grpc.GRPC_CANSignalData{
		Cansignals: grpccansignals,
	}

	for i, cs := range data {
		msg.Cansignals[i] = &kafka_grpc.GRPC_CANSignal{
			Vin:         cs.VIN,
			Timestamp:   cs.Timestamp,
			Id:          int32(cs.ID),
			Name:        cs.Name,
			Value:       cs.Value,
			Description: cs.Description,
		}
	}

	batchPayload := kafka_grpc.GRPC_CANSignalBatchPayload{
		Data: &msg,
	}

	return &batchPayload
}
