package models

import (
	"time"

	"code.justin.tv/common/yimg"
)

type UploadImageEvent struct {
	UserID    string      `json:"user_id"`
	Type      string      `json:"type"`
	ImageType string      `json:"image_type"`
	NewImage  yimg.Images `json:"new_image"`
	Status    string      `json:"status"`
	UploadID  string      `json:"upload_id"`
}

type UpdateChannelPropertiesEvent struct {
	ChannelID string  `json:"channel_id"`
	Type      string  `json:"type"`
	Channel   string  `json:"channel"`
	OldStatus *string `json:"old_status"`
	Status    *string `json:"status"`
	OldGame   *string `json:"old_game"`
	Game      *string `json:"game"`
	OldGameID *uint64 `json:"old_game_id"`
	GameID    *uint64 `json:"game_id"`
}

type UpdateUserPropertiesEvent struct {
	UserID    string                  `json:"user_id"`
	Type      string                  `json:"type"`
	Timestamp time.Time               `json:"timestamp"`
	Original  PropertiesUpdatePrivate `json:"original"`
	Changed   PropertiesUpdatePrivate `json:"changed"`
}

// ChannelTosViolationEvent is sent to pubsub on video-playback.<channel_name>
// and video-playback-by-id.<channel_id> when a channel gets a TOS strike.
type ChannelTosViolationEvent struct {
	Type       string  `json:"type"`
	ServerTime float64 `json:"server_time"`
}

// PropertiesUpdatePrivate represents the updateable properties that can be
// exposed to the user who they belong to.
// This notably omits such fields as RemoteIP, Location, and BannedUntil.
type PropertiesUpdatePrivate struct {
	Birthday      *time.Time `json:"birthday,omitempty"`
	Description   *string    `json:"description,omitempty"`
	Displayname   *string    `json:"displayname,omitempty"`
	EmailVerified *bool      `json:"email_verified,omitempty"`
	Language      *string    `json:"language,omitempty"`
	LastLogin     *string    `json:"last_login,omitempty"`
	Login         *string    `json:"login,omitempty"`
}

// ExtractUpdate creates a pair of PropertiesUpdatePrivate structs representing
// the changes being made to a user's properties. Only fields that are being
// updated will be non-nil in these structs. If no visible fields are being updated,
// the 'updated' boolean will be false.
func (p Properties) ExtractUpdate(up *UpdateableProperties) (original, changed PropertiesUpdatePrivate, updated bool) {
	if up == nil {
		return
	}
	updated = false
	if up.Birthday != nil && TimeValue(up.Birthday) != TimeValue(p.Birthday) {
		updated = true
		original.Birthday = p.Birthday
		changed.Birthday = up.Birthday
	}
	if up.Description != nil && StringValue(up.Description) != StringValue(p.Description) {
		updated = true
		original.Description = p.Description
		changed.Description = up.Description
	}
	if up.Displayname != nil && StringValue(up.Displayname) != StringValue(p.Displayname) {
		updated = true
		original.Displayname = p.Displayname
		changed.Displayname = up.Displayname
	}
	if up.EmailVerified != nil && BoolValue(up.EmailVerified) != BoolValue(p.EmailVerified) {
		updated = true
		original.EmailVerified = p.EmailVerified
		changed.EmailVerified = up.EmailVerified
	}
	if up.Language != nil && StringValue(up.Language) != StringValue(p.Language) {
		updated = true
		original.Language = p.Language
		changed.Language = up.Language
	}
	if up.LastLogin != nil && StringValue(up.LastLogin) != StringValue(p.LastLogin) {
		updated = true
		original.LastLogin = p.LastLogin
		changed.LastLogin = up.LastLogin
	}
	if up.NewLogin != nil && StringValue(up.NewLogin) != StringValue(p.Login) {
		updated = true
		original.Login = p.Login
		changed.Login = up.NewLogin
	}
	return
}

func StringValue(s *string) string {
	if s == nil {
		return ""
	} else {
		return *s
	}
}

func TimeValue(t *time.Time) time.Time {
	if t == nil {
		return time.Time{}
	} else {
		return *t
	}
}
func BoolValue(b *bool) bool {
	if b == nil {
		return false
	} else {
		return *b
	}
}
