package orm

import (
	"net/http"

	"github.com/jinzhu/gorm"
	"gogs.carducci-dante.gov.it/karmen/core/renderer"
)

type Activity struct {
	gorm.Model

	Name string

	Class         *Class
	Teacher       *Teacher
	SupplyTeacher *Teacher
	Subject       *Subject
	Student       *Student

	GroupActivity      bool
	GroupActivityHours int `schema:"group_activity_hours"`

	ClassID         uint `schema:"class_id"`
	TeacherID       uint `schema:"teacher_id"`
	SupplyTeacherID uint `schema:"supply_teacher_id"`
	SubjectID       uint `schema:"subject_id"`
	StudentID       uint `schema:"student_id"`

	Hours int

	prevTeacherID uint
}

type ActivityForUpdate struct {
	Activity Activity

	AllClasses  []*Class
	AllSubjects []*Subject
	AllTeachers []*Teacher
	AllStudents []*Student

	SelectedStudent       map[uint]string
	SelectedTeacher       map[uint]string
	SelectedSupplyTeacher map[uint]string
	SelectedSubject       map[uint]string
	SelectedClass         map[uint]string
}

type ActivityForAdd struct {
	AllClasses  []*Class
	AllSubjects []*Subject
	AllTeachers []*Teacher
	AllStudents []*Student
}

func (a *Activity) GetID() uint { return a.ID }

func GetActivity(args map[string]string) (interface{}, error) {
	var activity Activity
	if err := DB().First(&activity, args["id"]).Error; err != nil {
		return nil, err
	}
	return &activity, nil
}

func GetActivityAll(args map[string]string) (interface{}, error) {
	var activity Activity

	id := args["id"]

	if err := DB().Preload("Student").Preload("Teacher").Preload("Subject").Preload("Class").First(&activity, id).Error; err != nil {
		return nil, err
	}
	return &activity, nil
}

func GetActivityForUpdate(args map[string]string) (interface{}, error) {
	var data ActivityForUpdate

	id := args["id"]

	if err := DB().Preload("SupplyTeacher").Preload("Teacher").Preload("Subject").Preload("Class").First(&data.Activity, id).Error; err != nil {
		return nil, err
	}

	if err := DB().Find(&data.AllClasses).Error; err != nil {
		return nil, err
	}

	if err := DB().Find(&data.AllSubjects).Error; err != nil {
		return nil, err
	}

	if err := DB().Find(&data.AllTeachers).Error; err != nil {
		return nil, err
	}

	if err := DB().Find(&data.AllStudents).Error; err != nil {
		return nil, err
	}

	data.SelectedTeacher = make(map[uint]string)
	data.SelectedTeacher[data.Activity.TeacherID] = "selected"

	data.SelectedSupplyTeacher = make(map[uint]string)
	data.SelectedSupplyTeacher[data.Activity.SupplyTeacherID] = "selected"

	data.SelectedStudent = make(map[uint]string)
	data.SelectedStudent[data.Activity.StudentID] = "selected"

	data.SelectedClass = make(map[uint]string)
	data.SelectedClass[data.Activity.ClassID] = "selected"

	data.SelectedSubject = make(map[uint]string)
	data.SelectedSubject[data.Activity.SubjectID] = "selected"
	return data, nil
}

func GetActivityForAdd(args map[string]string) (interface{}, error) {
	var data ActivityForAdd

	if err := DB().Find(&data.AllClasses).Error; err != nil {
		return nil, err
	}

	if err := DB().Find(&data.AllSubjects).Error; err != nil {
		return nil, err
	}

	if err := DB().Find(&data.AllTeachers).Error; err != nil {
		return nil, err
	}

	if err := DB().Find(&data.AllStudents).Error; err != nil {
		return nil, err
	}

	return data, nil
}

func GetActivitiesAll(args map[string]string) (interface{}, error) {
	var activities []*Activity
	if err := DB().Preload("Teacher").Preload("Subject").Preload("Class").Order("name").Find(&activities).Error; err != nil {
		return nil, err
	}
	return activities, nil
}

func GetActivities(args map[string]string) (interface{}, error) {
	var activities []*Activity
	if err := DB().Order("surname,name").Find(&activities).Error; err != nil {
		return nil, err
	}
	return activities, nil
}

func SaveActivity(activity interface{}) (interface{}, error) {
	if err := DB().Save(activity).Error; err != nil {
		return nil, err
	}
	return activity, nil
}

func UpdateActivity(args map[string]string, r *http.Request) (IDer, error) {
	activity, err := GetActivity(args)
	if err != nil {
		return nil, err
	}
	err = renderer.Decode(activity, r)
	if err != nil {
		return nil, err
	}
	_, err = SaveActivity(activity)
	if err != nil {
		return nil, err
	}
	activity, err = GetActivity(args)
	if err != nil {
		return nil, err
	}
	return activity.(*Activity), nil
}

func AddActivity(args map[string]string, r *http.Request) (IDer, error) {
	activity := new(Activity)
	err := renderer.Decode(activity, r)
	if err != nil {
		return nil, err
	}
	activity, err = CreateActivity(activity)
	if err != nil {
		return nil, err
	}
	return activity, nil
}

func CreateActivity(activity *Activity) (*Activity, error) {
	if err := DB().Create(activity).Error; err != nil {
		return nil, err
	}
	return activity, nil
}

func DeleteActivity(args map[string]string, r *http.Request) (IDer, error) {
	activity, err := GetActivity(args)
	if err != nil {
		return nil, err
	}
	if err := DB().Unscoped().Delete(activity.(*Activity)).Error; err != nil {
		return nil, err
	}
	return activity.(*Activity), nil
}
