//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
//Copyright (C) 2024 HTWKalender support@htwkalender.de

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU Affero General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU Affero General Public License for more details.

//You should have received a copy of the GNU Affero General Public License
//along with this program.  If not, see <https://www.gnu.org/licenses/>.

package model

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"
)

// DefaultDateLayout specifies the default app date strings layout.
const DefaultDateLayout = "2006-01-02 15:04:05.000Z"

// IcalModel local type for EmitICal function
type IcalModel struct {
	Events  Events
	Mapping map[string]FeedCollection
}

// FeedModel is an iCal feed
type FeedModel struct {
	Content   string
	ExpiresAt JSONTime
	Semester  string
	Course    string
}

// Entry is a time entry
type Entry struct {
	DateStart   JSONTime `json:"dateStart"`
	DateEnd     JSONTime `json:"dateEnd"`
	Description string   `json:"description"`
}

// Entries is a collection of entries
type Entries []*Entry

type FeedModule struct {
	UUID            string `db:"uuid" json:"uuid"`
	Name            string `db:"Name" json:"name"`
	Course          string `db:"course" json:"course"`
	UserDefinedName string `db:"userDefinedName" json:"userDefinedName"`
	Reminder        bool   `db:"reminder" json:"reminder"`
}

type FeedRecord struct {
	Modules   []FeedModule `db:"modules" json:"modules"`
	Retrieved JSONTime     `db:"retrieved" json:"retrieved"`
	BaseModel
}

type JSONTime time.Time

// MarshalJSON Implement Marshaler and Unmarshaler interface
func (j JSONTime) MarshalJSON() ([]byte, error) {
	return json.Marshal(time.Time(j))
}

func (jt *JSONTime) UnmarshalJSON(b []byte) error {
	timeString := strings.Trim(string(b), `"`)
	if timeString == "null" || timeString == "" {
		return nil
	}
	t, err := time.Parse(DefaultDateLayout, timeString)
	if err == nil {
		*jt = JSONTime(t)
		return nil
	}
	return fmt.Errorf("error parsing time string %s: %w", timeString, err)
}

func ToJSONTime(timeString string) JSONTime {
	t, err := time.Parse(DefaultDateLayout, timeString)
	if err != nil {
		return JSONTime(time.Time{})
	}
	return JSONTime(t)
}
