package identicon

import (
	"math"

	"git.mstar.dev/mstar/canvas"
	mathutils "git.mstar.dev/mstar/goutils/math"
)

type shape struct {
	canvas      *canvas.Canvas
	hash        int
	primary     string
	secondary   string
	pos         vec2
	scale       float64
	cellSize    int
	strokeColor string
}

func (s *shape) GetColor() string {
	if mathutils.Abs(s.hash) == 0 {
		return s.primary
	} else {
		return s.secondary
	}
}

func (s *shape) MakePath() {
	mod := mathutils.Abs(s.hash+1) % 4
	switch mod {
	case 0:
		// square
		s.canvas.BeginPath()
		s.canvas.MoveTo(float64(s.pos.X), float64(s.pos.Y))
		s.canvas.LineTo(float64(s.pos.X+float64(s.cellSize/2)), float64(s.pos.Y))
		s.canvas.LineTo(
			float64(s.pos.X+float64(s.cellSize/2)),
			float64(s.pos.Y-float64(s.cellSize/2)),
		)
		s.canvas.LineTo(float64(s.pos.X), float64(s.pos.Y-float64(s.cellSize/2)))
		s.canvas.ClosePath()
	case 1:
		// circle
		s.canvas.BeginPath()
		s.canvas.Arc(
			float64(s.pos.X)+float64(s.cellSize)/math.Pi-5,
			float64(s.pos.Y)-float64(s.cellSize)/math.Pi+5,
			float64(s.cellSize)/3,
			0,
			math.Pi*2,
			true,
		)
	case 2:
		// triangle
		s.canvas.BeginPath()
		s.canvas.MoveTo(float64(s.pos.X), float64(s.pos.Y))
		s.canvas.LineTo(float64(s.pos.X)+float64(s.cellSize)*0.65, float64(s.pos.Y))
		s.canvas.LineTo(float64(s.pos.X), float64(s.pos.Y)-float64(s.cellSize)*0.65)
		s.canvas.ClosePath()
	case 3:
		// oval
		s.canvas.BeginPath()
		s.canvas.MoveTo(
			float64(s.pos.X)-float64(s.cellSize)*0.2,
			float64(s.pos.Y)+float64(s.cellSize)*0.2,
		)
		s.canvas.QuadraticCurveTo(
			float64(s.pos.X)+float64(s.cellSize)*0.4,
			float64(s.pos.Y),
			float64(s.pos.X)+float64(s.cellSize)*0.5,
			float64(s.pos.Y)-float64(s.cellSize)*0.5,
		)
		s.canvas.MoveTo(
			float64(s.pos.X)+float64(s.cellSize)*0.5,
			float64(s.pos.Y)-float64(s.cellSize)*0.5,
		)
		s.canvas.QuadraticCurveTo(
			float64(s.pos.X),
			float64(s.pos.Y)-float64(s.cellSize)*0.4,
			float64(s.pos.X)-float64(s.cellSize)*0.2,
			float64(s.pos.Y)+float64(s.cellSize)*0.2,
		)
	default:
		// square
		s.canvas.BeginPath()
		s.canvas.MoveTo(float64(s.pos.X), float64(s.pos.Y))
		s.canvas.LineTo(float64(s.pos.X+float64(s.cellSize/2)), float64(s.pos.Y))
		s.canvas.LineTo(
			float64(s.pos.X+float64(s.cellSize/2)),
			float64(s.pos.Y-float64(s.cellSize/2)),
		)
		s.canvas.LineTo(float64(s.pos.X), float64(s.pos.Y-float64(s.cellSize/2)))
		s.canvas.ClosePath()
	}
}

func (s *shape) Draw(hasStroke bool, strokeWeight int) {
	color := s.GetColor()
	// THIS SHIT ISN'T IMPLEMENTED! I hope it will work regardless
	// s.canvas.SetGlobalCompositeOperation("source-over")
	s.MakePath()
	s.canvas.SetFillStyle(color)
	s.canvas.SetStrokeStyle(s.strokeColor)
	s.canvas.SetLineWidth(s.scale * (4 / 5 * float64(strokeWeight)) / float64(canvasSize))
	s.canvas.SetLineJoin(canvas.Round)
	s.canvas.SetLineCap(canvas.Round)
	s.canvas.Fill()
	if hasStroke {
		s.canvas.Stroke()
	}
}
