package main

import (
	"git.wtrh.nl/3D-models/objects"
	"github.com/deadsy/sdfx/render"
	"github.com/deadsy/sdfx/sdf"
	"math"
)

type Button struct {
	Size float64 // diameter of button
	Thickness float64 // height of button
	HoleSpacing float64 // Broadest cross length of thread holes.
	Curve float64 // Depth of the curve
}

type DoveTail struct {
	Size sdf.V3
	Angle float64
}

var flange_h = 1.0
var flange_w = 2.0
var cloth_offset = 1.0

var doveTail = DoveTail{
	Size: sdf.V3{X: 10, Y: 8, Z: 2},
	Angle: sdf.Pi/10,
}

func ButtonHolder3D(b *Button) (holder sdf.SDF3, err error) {
	cylinderTickness := flange_h+cloth_offset+b.Curve
	holder, err = sdf.Cylinder3D(cylinderTickness,b.Size/2+flange_w,0.0)
	if err != nil {
		return
	}
	negative, err := buttonNegative(b)
	if err != nil {
		return
	}
	holder = sdf.Transform3D(holder, sdf.Translate3d(sdf.V3{0,0,cylinderTickness/2}))
	negative = sdf.Transform3D(negative, sdf.Translate3d(sdf.V3{0,0,cloth_offset}))
	negative2, err := wireNegative(b)
	if err != nil {
		return
	}
	negative = sdf.Union3D(negative2,negative)
	holder = sdf.Difference3D(holder,negative)
	return
}

func buttonNegative(b *Button) (negative sdf.SDF3, err error) {
	h := (math.Pow(b.Size/2,2)/b.Curve - b.Curve)/2
	s1, err := sdf.Sphere3D(h)
	if err != nil {
		return
	}
	s1 = sdf.Transform3D(s1, sdf.Translate3d(sdf.V3{0,0,h}))
	c1, err := sdf.Cylinder3D(h,b.Size/2,0.0)
	if err != nil {
		return
	}
	c1 = sdf.Transform3D(c1, sdf.Translate3d(sdf.V3{0,0,h/2}))
	negative = sdf.Intersect3D(s1,c1)
	return
}

func wireNegative(b *Button) (negative sdf.SDF3, err error) {
	size := sdf.V3{X: b.HoleSpacing/2, Y: b.HoleSpacing/2, Z: 20}.MulScalar(math.Sqrt(2))
	b1, err := sdf.Box3D(size,1.5)
	if err != nil {
		return
	}
	b1 = sdf.Transform3D(b1,sdf.RotateZ(sdf.Pi/4))
	b1 = sdf.Elongate3D(b1,sdf.V3{X:b.Size,Y: 0, Z: 0})
	negative =  sdf.Transform3D(b1,sdf.Translate3d(sdf.V3{-b.Size/2,0,0}))
	return
}

func dovetail(size sdf.V3, angle float64, offset float64) (tail sdf.SDF3, err error) {
	tail, err = sdf.Box3D(size, 0.0)
	a1 := sdf.V3{X: 0, Y: size.Y/2+offset, Z:-size.Z/2}
	a2 := sdf.V3{X: 0, Y: -size.Y/2+offset, Z:-size.Z/2}
	n1 := sdf.V3{Y: -math.Cos(angle), X: 0, Z: -math.Sin(angle)}
	n2 := sdf.V3{Y: math.Cos(angle), X: 0, Z: -math.Sin(angle)}
	tail = sdf.Cut3D(tail, a1, n1)
	tail = sdf.Cut3D(tail, a2, n2)
	//bottomSize := sdf.V2{X: doveTail.Size.X, Y: doveTail.Size.Y}
	//b2d := sdf.Box2D(bottomSize,0)
	//topSize := bottomSize.Add(sdf.V2{X:0, Y: doveTail.Size.Z * math.Tan(doveTail.Angle) * 2})
	//t2d := sdf.Box2D(topSize,0)
	//tail, err = sdf.Loft3D(b2d, t2d, doveTail.Size.Z,0)
	return
}

func main() {
	k := objects.BoxParams{
		Size: sdf.V3{100,100,100},
		Wall: 3,
		BottomTopRatio: 1,
		Margin: 0.1,
		Taper: 0.1,
		ClosingHeight: 4,
		CornerRadius: 3,
	}
	box, err := objects.BottomBox3D(&k)
	if err != nil {
		return
	}
	render.RenderSTL(box, 300, "out.stl")
	b := Button{
		Size: 18,
		Curve: 1.2,
		HoleSpacing: 8.5,
	}

	holder, err := ButtonHolder3D(&b)
	if err != nil {
		return
	}
	render.RenderSTL(holder, 300, "holder.stl")
	negative, err := wireNegative(&b)
	if err != nil {
		return
	}
	render.RenderSTL(negative, 300, "negative.stl")
	return
}