package orm

import (
	"errors"

	"github.com/jinzhu/gorm"
)

type Teacher struct {
	gorm.Model
	Credential
	Classes     []*Class
	Subjects    []*Subject
	Activities  []*Activity
	Departments []*Department
	Issues      []*Issue
	Hours       int
	CurrHours   int
	TheBossId   uint
}

var (
	selectDistinctTeachers = `
SELECT teachers.* FROM activities
INNER JOIN teachers ON activities.teacher_id=teachers.id
`
	selectUniqueTeacherClasses = `
SELECT DISTINCT classes.* FROM activities 
INNER JOIN classes on classes.id=activities.class_id 
WHERE teacher_id=?`

	selectUniqueTeacherSubjects = `
SELECT DISTINCT subjects.* FROM activities 
INNER JOIN subjects on subjects.id=activities.subject_id 
WHERE activities.teacher_id=?`
)

func GetTeacher(id string) (*Teacher, error) {
	var teacher Teacher
	if err := DB().First(&teacher, id).Error; err != nil {
		return nil, err
	}
	return &teacher, nil
}

func GetTeacherAll(id string) (*Teacher, error) {
	var teacher Teacher
	if err := DB().First(&teacher, id).Error; err != nil {
		return nil, err
	}

	if err := DB().Raw(selectUniqueTeacherClasses, id).Scan(&teacher.Classes).Error; err != nil {
		return nil, err
	}

	if err := DB().Raw(selectUniqueTeacherSubjects, id).Scan(&teacher.Subjects).Error; err != nil {
		return nil, err
	}

	if err := DB().Preload("Teacher").Preload("Subject").Where("teacher_id=?", id).Find(&teacher.Activities).Error; err != nil {
		return nil, err
	}

	return &teacher, nil
}

func GetTeachers() ([]*Teacher, error) {
	var teachers []*Teacher
	if err := DB().Order("surname,name").Find(&teachers).Error; err != nil {
		return nil, err
	}
	return teachers, nil
}

func GetTeachersAll() ([]*Teacher, error) {
	var teachers []*Teacher
	if err := DB().Order("surname,name").Find(&teachers).Error; err != nil {
		return nil, err
	}
	for _, teacher := range teachers {
		teacher.GetClasses()
	}
	for _, teacher := range teachers {
		teacher.GetSubjects()
	}

	return teachers, nil
}

func SaveTeacher(teacher *Teacher) (*Teacher, error) {
	if err := DB().Save(&teacher).Error; err != nil {
		return nil, err
	}
	return teacher, nil
}

func CreateTeacher(teacher *Teacher) (*Teacher, error) {
	if err := DB().Create(teacher).Error; err != nil {
		return nil, err
	}
	return teacher, nil
}

func (t *Teacher) GetClasses() ([]*Class, error) {
	if err := DB().Raw(selectUniqueTeacherClasses, t.ID).Scan(&t.Classes).Error; err != nil {
		return nil, err
	}
	return t.Classes, nil
}

func (t *Teacher) GetSubjects() ([]*Subject, error) {
	if err := DB().Raw(selectUniqueTeacherSubjects, t.ID).Scan(&t.Subjects).Error; err != nil {
		return nil, err
	}
	return t.Subjects, nil
}

func (t *Teacher) GetActivitiesByClass(id string) ([]*Activity, error) {
	if err := DB().Preload("Teacher").Where("class_id=? AND teacher_id=?", id, t.ID).Find(&t.Activities).Error; err != nil {
		return nil, err
	}
	return t.Activities, nil
}

func (t *Teacher) Create(db *gorm.DB, record map[string]interface{}) error {
	result := new(Teacher)

	if name := record["name"]; name == nil {
		return errors.New("Error in creating teacher: field name is empty")
	} else {
		result.Name = name.(string)
	}
	if surname := record["surname"]; surname == nil {
		return errors.New("Error in creating teacher: field surname is empty")
	} else {
		result.Surname = surname.(string)
	}

	db.Create(result)

	return nil
}

func (t *Teacher) IsCoordinator() ([]*Class, error) {
	var output []*Class

	classes, err := t.GetClasses()
	if err != nil {
		return nil, err
	}

	for _, class := range classes {
		if class.CoordinatorID == t.ID {
			output = append(output, class)
		}
	}
	return output, nil
}

func (t *Teacher) IsMinuter() ([]*Class, error) {
	var output []*Class

	classes, err := t.GetClasses()
	if err != nil {
		return nil, err
	}

	for _, class := range classes {
		if class.MinuterID == t.ID {
			output = append(output, class)
		}
	}
	return output, nil
}

func (t Teacher) IsCoordinatorInClass(className string) bool {
	var classes []Class

	if err := DB().Model(t).Where("name = ?", className).Related(&classes, "Classes").Error; err != nil {
		panic(err)
	}

	for _, class := range classes {
		if class.CoordinatorID == t.ID {
			return true
		}
	}

	return false

}
