package main

import (
	"bufio"
	"encoding/csv"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"strings"
	"time"
)

type MyTime time.Time

func (mt *MyTime) UnmarshalJSON(b []byte) error {
	s := strings.Trim(string(b), "\"")
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		return err
	}
	*mt = MyTime(t)
	return nil
}

func ParseDate(b string) MyTime {
	s := strings.Trim(b, "\"")
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		return MyTime{}
	}
	return MyTime(t)
}

func (mt *MyTime) ParseDate(b []byte) error {
	s := strings.Trim(string(b), "\"")
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		return err
	}
	*mt = MyTime(t)
	return nil
}

func (mt MyTime) MarshalJSON() ([]byte, error) {
	return json.Marshal(mt)
}

var months = map[string]string{
	"1":  "Jan",
	"2":  "Feb",
	"3":  "Mrt",
	"4":  "Apr",
	"5":  "Mei",
	"6":  "Jun",
	"7":  "Jul",
	"8":  "Aug",
	"9":  "Sept",
	"10": "Okt",
	"11": "Nov",
	"12": "Dec",
}

var monthsLong = map[string]string{
	"1":  "Januari",
	"2":  "Februari",
	"3":  "Maart",
	"4":  "April",
	"5":  "Mei",
	"6":  "Juni",
	"7":  "July",
	"8":  "Augustus",
	"9":  "September",
	"10": "Oktober",
	"11": "November",
	"12": "December",
}

func (mt MyTime) Format() string {
	t := time.Time(mt)
	return fmt.Sprintf("%v %v %v", t.Format("02"), months[t.Format("1")], t.Format("2006"))
}

func (mt MyTime) Title() string {
	t := time.Time(mt)
	return fmt.Sprintf("%v %v", monthsLong[t.Format("1")], t.Format("2006"))
}

type EventFlags struct {
	Soldout  bool
	Tryout   bool
	Premiere bool
	Preview  bool
	XL       bool
	Solo     bool
	Duo      bool
}

type Event struct {
	Date  MyTime     `json:"date"`
	Venue string     `json:"venue"`
	City  string     `json:"city"`
	Link  string     `json:"link"`
	Flags EventFlags `json:"flags"`
}

func (e *Event) SetFlags(flags string) {
	for _, flag := range strings.Split(flags, ",") {
		switch strings.Trim(strings.ToLower(flag), " \t") {
		case "uitverkocht":
			e.Flags.Soldout = true
		case "tryout":
			e.Flags.Tryout = true
		case "preview":
			e.Flags.Preview = true
		case "premiere":
			e.Flags.Premiere = true
		case "solo":
			e.Flags.Solo = true
		case "xl":
			e.Flags.XL = true
		case "duo":
			e.Flags.Duo = true
		}
	}
}

func getEvents(tour string) *[][]Event {
	var events [][]Event

	f, err := os.Open(path.Join(ROOT_DIR, fmt.Sprintf("data/%s_tour.csv", tour)))
	if err != nil {
		log.Fatal(err)
	}

	defer f.Close()

	eventsAll := []Event{}

	reader := csv.NewReader(bufio.NewReader(f))
	reader.Comma = ';'

	now := time.Now()

	for {
		line, error := reader.Read()
		if error == io.EOF {
			break
		} else if error != nil {
			log.Fatal(error)
		}

		if line[0] == "date" {
			continue
		}

		if now.After(
			(time.Time(ParseDate(line[0]))).Local().Add(time.Hour * time.Duration(24)),
		) {
			continue
		}

		event := Event{
			Date:  ParseDate(line[0]),
			Venue: line[2],
			City:  line[1],
			Link:  line[3],
		}

		event.SetFlags(line[4])

		eventsAll = append(eventsAll, event)

	}

	months := []string{}
	eventsByMonth := map[string][]Event{}

	for _, event := range eventsAll {
		m := time.Time(event.Date).Format("01")
		if _, ok := eventsByMonth[m]; ok {
			eventsByMonth[m] = append(eventsByMonth[m], event)
		} else {
			months = append(months, m)
			eventsByMonth[m] = []Event{event}
		}
	}

	for _, m := range months {
		events = append(events, eventsByMonth[m])
	}

	return &events
}
