package schema

import (
	"context"
	"encoding/base64"
	"os"
	"strings"
	"time"

	"xorm.io/builder"
)

func init() {
	RegisterModel(new(Radio))
}

type Radio struct {
	ID              int64      `xorm:"pk autoincr" json:"id"`
	Name            string     `xorm:"not null unique" json:"name"`
	IsOnline        bool       `xorm:"bool not null default false" json:"is_online"`
	Manufacturer    string     `xorm:"varchar(64) not null" json:"manufacturer"`
	Device          *string    `xorm:"varchar(64)" json:"device"`
	FirmwareVersion *string    `xorm:"varchar(32)" json:"firmware_version"`
	FirmwareDate    *time.Time `json:"firmware_date"`
	Antenna         *string    `xorm:"varchar(100)" json:"antenna"`
	Modulation      string     `xorm:"varchar(16) not null" json:"modulation"`
	Protocol        string     `xorm:"varchar(16) not null index" json:"protocol"`
	Latitude        *float64   `json:"latitude,omitempty"`
	Longitude       *float64   `json:"longitude,omitempty"`
	Altitude        *float64   `json:"altitude,omitempty"`
	Frequency       float64    `xorm:"not null" json:"frequency"`
	Bandwidth       float64    `xorm:"not null" json:"bandwidth"`
	Power           *float64   `json:"power,omitempty"`
	Gain            *float64   `json:"gain,omitempty"`
	LoRaSF          *uint8     `xorm:"smallint 'lora_sf'" json:"lora_sf,omitempty"`
	LoRaCR          *uint8     `xorm:"smallint 'lora_cr'" json:"lora_cr,omitempty"`
	Extra           []byte     `xorm:"jsonb" json:"extra,omitempty"`
	CreatedAt       time.Time  `xorm:"timestamp not null default current_timestamp" json:"created_at"`
	UpdatedAt       time.Time  `xorm:"timestamp not null default current_timestamp" json:"updated_at"`
}

func GetRadioByEncodedID(ctx context.Context, id string) (*Radio, error) {
	name, err := base64.RawURLEncoding.DecodeString(strings.TrimRight(id, "="))
	if err != nil {
		return nil, err
	}

	radio := new(Radio)
	has, err := Query(ctx).Where(builder.Eq{"`name`": name}).Get(radio)
	if err != nil {
		return nil, err
	} else if !has {
		return nil, os.ErrNotExist
	}
	return radio, nil
}

func GetRadios(ctx context.Context) ([]*Radio, error) {
	radios := make([]*Radio, 0, 5)
	return radios, Query(ctx).Find(&radios)
}

func GetRadiosByProtocol(ctx context.Context, protocol string) ([]*Radio, error) {
	radios := make([]*Radio, 0, 5)
	return radios, Query(ctx).
		Where(builder.Eq{"`protocol`": protocol}).
		Find(&radios)
}

func GetRadiosRecentlyOnline(ctx context.Context) ([]*Radio, error) {
	radios := make([]*Radio, 0, 5)
	return radios, Query(ctx).
		Where(builder.Eq{"`is_online`": true}).
		Find(&radios)
}
