package serverless

import (
	"net/url"
	"time"
)

const jsonTimeFormat = `"2006-01-02 15:04:05.000"`
const urlTimeFormat = `2006-01-02 15:04:05.000`

type JSONTime time.Time

// MarshalJSON used to specify the time format
func (t JSONTime) MarshalJSON() ([]byte, error) {
	stamp := time.Time(t).Format(jsonTimeFormat)
	return []byte(stamp), nil
}

// UnmarshalJSON is used to parse time.Time from bytes. The builtin json.Unmarshal function cannot unmarshal
// a date string formatted as "2006-01-02 15:04:05.000", so we must implement a customized unmarshal function.
func (t *JSONTime) UnmarshalJSON(data []byte) error {
	tm, err := time.Parse(jsonTimeFormat, string(data))
	if err != nil {
		return err
	}

	*t = JSONTime(tm)
	return nil
}

func (t *JSONTime) UrlTimeStr() string {
	timeStr := time.Time(*t).Format(urlTimeFormat)
	return url.PathEscape(timeStr)
}

type WhitelistResponse struct {
	Keyspace  string `json:"keyspace,omitempty"` // Same with token
	IsAllowed bool   `json:"is_allowed,omitempty"`
}

type ListBackupRequest struct {
	LastBackupTime JSONTime `json:"lastbackuptime,omitempty"`
	MaxCount       uint64   `json:"maxcount,omitempty"`
}

type BackupItem struct {
	ID   uint64   `json:"id,omitempty"`
	Name string   `json:"name,omitempty"`
	Time JSONTime `json:"time,omitempty"`
}

type ListBackupResponse struct {
	Items   []BackupItem `json:"items,omitempty"`
	HasMore bool         `json:"has_more,omitempty"`
}

// Either `Backup` or `PointInTime` must be specified.
type RestoreRequest struct {
	Backup      *BackupItem `json:"backup,omitempty"`
	PointInTime *JSONTime   `json:"point_in_time,omitempty"`
	Token       string      `json:"token,omitempty"`
	ID          uint64      `json:"id,omitempty"`
	SourceToken *string     `json:"source_token,omitempty"`
}

type RestoreStatus string

const (
	RestorePending RestoreStatus = "Pending"
	RestoreInit    RestoreStatus = "Init"
	RestoreRunning RestoreStatus = "Running"
	RestoreSucceed RestoreStatus = "Succeed"
	RestoreError   RestoreStatus = "Error"
)

type RestoreProgress struct {
	Step     string `json:"step,omitempty"`
	Progress int32  `json:"progress,omitempty"`
}

type RestoreProgressResponse struct {
	Status       RestoreStatus   `json:"status,omitempty"`
	Error        string          `json:"error,omitempty"`
	RestoreBytes uint64          `json:"restore_bytes,omitempty"`
	Progress     RestoreProgress `json:"progress,omitempty"`
}
