package orm

import "github.com/jinzhu/gorm"

type Activity struct {
	gorm.Model
	Name      string
	Class     Class
	Teacher   Teacher
	Subject   Subject
	ClassID   uint `schema:"class_id"`
	TeacherID uint `schema:"teacher_id"`
	SubjectID uint `schema:"subject_id"`
	Hours     int

	prevTeacherID uint
}

func (a *Activity) updateRelatedTeacher(tx *gorm.DB, teacherID uint) {
	var (
		teacher Teacher
		class   Class
		subject Subject
	)
	if err := tx.Find(&teacher, teacherID).Error; err != nil {
		panic(err)
	}

	// Calculate teacher hours

	teacher.CalcHours(tx)

	// Teacher -> Classes association

	if err := tx.First(&class, a.ClassID).Error; err != nil {
		panic(err)
	}

	if err := tx.Model(&teacher).Association("Classes").Append(class).Error; err != nil {
		panic(err)
	}

	// Teacher -> Subjects association

	if err := tx.First(&subject, a.SubjectID).Error; err != nil {
		panic(err)
	}

	if err := tx.Model(&teacher).Association("Subjects").Append(subject).Error; err != nil {
		panic(err)
	}

}

func (a *Activity) deleteRelatedTeacherAssociations(tx *gorm.DB, teacherID uint) {
	var (
		teacher Teacher
		class   Class
		subject Subject
	)
	if err := tx.Find(&teacher, teacherID).Error; err != nil {
		panic(err)
	}

	// Calculate teacher hours

	teacher.CalcHours(tx)

	// Teacher -> Classes association

	if err := tx.First(&class, a.ClassID).Error; err != nil {
		panic(err)
	}

	if err := tx.Preload("Classes").Find(&teacher, teacher.ID).Error; err != nil {
		panic(err)
	}

	if err := tx.Model(&teacher).Association("Classes").Delete(class).Error; err != nil {
		panic(err)
	}

	if err := tx.Preload("Classes").Find(&teacher, teacher.ID).Error; err != nil {
		panic(err)
	}

	// Teacher -> Subjects association

	if err := tx.First(&subject, a.SubjectID).Error; err != nil {
		panic(err)
	}

	if err := tx.Model(&teacher).Association("Subjects").Delete(subject).Error; err != nil {
		panic(err)
	}

}

func (a *Activity) createUpdateActivity(tx *gorm.DB) {
	if (a.TeacherID != a.prevTeacherID) && (a.prevTeacherID != 0) {
		a.deleteRelatedTeacherAssociations(tx, a.prevTeacherID)
	}
	if a.TeacherID != 0 {
		a.updateRelatedTeacher(tx, a.TeacherID)
	}
}

func (a *Activity) deleteActivity(tx *gorm.DB) {
	if a.TeacherID != 0 {
		var (
			teacher Teacher
			class   Class
			subject Subject
		)
		if err := tx.Find(&teacher, a.TeacherID).Error; err != nil {
			panic(err)
		}

		// Calculate teacher hours

		teacher.CalcHours(tx)

		// Teacher -> Classes association

		if err := tx.First(&class, a.ClassID).Error; err != nil {
			panic(err)
		}

		if err := tx.Model(&teacher).Association("Classes").Delete(class).Error; err != nil {
			panic(err)
		}

		// Teacher -> Subjects association

		if err := tx.First(&subject, a.SubjectID).Error; err != nil {
			panic(err)
		}

		if err := tx.Model(&teacher).Association("Subjects").Delete(subject).Error; err != nil {
			panic(err)
		}
	}

}

func (a *Activity) AfterCreate(tx *gorm.DB) error {
	a.createUpdateActivity(tx)
	return nil
}

func (a *Activity) BeforeUpdate(tx *gorm.DB) error {
	var currActivity Activity
	if err := tx.First(&currActivity, a.ID).Error; err != nil {
		panic(err)
	}
	a.prevTeacherID = currActivity.TeacherID
	return nil
}

func (a *Activity) AfterSave(tx *gorm.DB) error {
	a.createUpdateActivity(tx)
	return nil
}

// func (a *Activity) AfterUpdate(tx *gorm.DB) error {
// 	a.createUpdateActivity(tx)
// 	return nil
// }

func (a *Activity) AfterDelete(tx *gorm.DB) error {
	a.deleteActivity(tx)
	return nil
}
