// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// staticimg is where the StaticImg struct is defined.
// This struct contains image information for all images other than cards.

package staticimg

import (
	"golang.org/x/mobile/exp/f32"
	"golang.org/x/mobile/exp/sprite"
	"hearts/img/coords"
	"hearts/logic/card"
)

// Returns a new StaticImg object, with no variables set
func MakeStaticImg() *StaticImg {
	return &StaticImg{}
}

// Static Images may be buttons, drop targets, or any other image that is not a card object
type StaticImg struct {
	node  *sprite.Node
	image sprite.SubTex
	// alt may or may not be set. It is a second SubTex in case the staticImg may alternate between two displays
	// can be used as the 'pressed' image if the StaticImg instance is a button
	// also can be used as a 'blank' image if the StaticImg instance may disappear
	alt sprite.SubTex
	// displayingImage is true is image is currently being displayed, and false if alt is currently being displayed
	displayingImage bool
	pos             *coords.Position
	// cardHere is used if the StaticImg instance is a drop target
	cardHere *card.Card
}

// Returns the node of s
func (s *StaticImg) GetNode() *sprite.Node {
	return s.node
}

// Returns the image of s
func (s *StaticImg) GetImage() sprite.SubTex {
	return s.image
}

// Returns the alternate image of s
func (s *StaticImg) GetAlt() sprite.SubTex {
	return s.alt
}

func (s *StaticImg) GetDisplayingImage() bool {
	return s.displayingImage
}

func (s *StaticImg) GetPosition() *coords.Position {
	return s.pos
}

// Returns a vector containing the current x- and y-coordinate of the upper left corner of s
func (s *StaticImg) GetCurrent() *coords.Vec {
	return s.pos.GetCurrent()
}

// Returns a vector containing the initial x- and y-coordinate of the upper left corner of s
func (s *StaticImg) GetInitial() *coords.Vec {
	return s.pos.GetInitial()
}

// Returns a vector containing the width and height of s
func (s *StaticImg) GetDimensions() *coords.Vec {
	return s.pos.GetDimensions()
}

// Returns the card currently pinned to s
func (s *StaticImg) GetCardHere() *card.Card {
	return s.cardHere
}

// Returns the node of s
func (s *StaticImg) SetNode(n *sprite.Node) {
	s.node = n
}

// Sets the image of s to t
func (s *StaticImg) SetImage(t sprite.SubTex) {
	s.image = t
}

// Sets the alternate image of s to t
func (s *StaticImg) SetAlt(t sprite.SubTex) {
	s.alt = t
}

func (s *StaticImg) SetDisplayingImage(disp bool) {
	s.displayingImage = disp
}

// Moves s to a new position and size
func (s *StaticImg) Move(newXY, newDimensions *coords.Vec, eng sprite.Engine) {
	eng.SetTransform(s.node, f32.Affine{
		{newDimensions.X, 0, newXY.X},
		{0, newDimensions.Y, newXY.Y},
	})
	s.pos.SetCurrent(newXY)
	s.pos.SetDimensions(newDimensions)
}

// Sets the initial x and y coordinates of the upper left corner of s
func (s *StaticImg) SetPos(newPos *coords.Position) {
	s.pos = newPos
}

func (s *StaticImg) SetInitial(initial *coords.Vec) {
	s.pos.SetInitial(initial)
}

// Pins card c to s
func (s *StaticImg) SetCardHere(c *card.Card) {
	s.cardHere = c
}
