package orm

import (
	"path"
	"reflect"
	"strings"

	"github.com/jinzhu/inflection"
)

var (
	Get map[string]GetFn = map[string]GetFn{
		// Teacher
		"/teachers":             GetTeachersFast,
		"/teachers/{id}":        GetTeacherAll,
		"/teachers/{id}/update": GetTeacher,
		"/teachers/add/":        GetNothing,

		"/api/teachers":             GetTeachersAll,
		"/api/teachers/{id}":        GetTeacherAll,
		"/api/teachers/{id}/update": GetTeacher,
		"/api/teachers/add/":        GetNothing,

		// Student
		"/students":             GetStudentsFast,
		"/students/{id}":        GetStudentAll,
		"/students/{id}/update": GetStudentForUpdate,
		"/students/add/":        GetStudentForAdd,

		"/api/students":             GetStudentsAll,
		"/api/students/{id}":        GetStudentAll,
		"/api/students/{id}/update": GetStudentForUpdate,
		"/api/students/add/":        GetStudentForAdd,

		// Classes
		"/classes":             GetClassesAll,
		"/classes/{id}":        GetClassAll,
		"/classes/{id}/update": GetClassForUpdate,
		"/classes/add/":        GetClassForAdd,

		"/api/classes":             GetClassesAll,
		"/api/classes/{id}":        GetClassAll,
		"/api/classes/{id}/update": GetClassForUpdate,
		"/api/classes/add/":        GetClassForAdd,

		// Subjects
		"/subjects":             GetSubjectsAll,
		"/subjects/{id}":        GetSubjectAll,
		"/subjects/{id}/update": GetSubjectForUpdate,
		"/subjects/add/":        GetSubjectForAdd,

		"/api/subjects":             GetSubjectsAll,
		"/api/subjects/{id}":        GetSubjectAll,
		"/api/subjects/{id}/update": GetSubjectForUpdate,
		"/api/subjects/add/":        GetSubjectForAdd,

		// Departments
		"/departments":             GetDepartmentsAll,
		"/departments/{id}":        GetDepartmentAll,
		"/departments/{id}/update": GetDepartmentForUpdate,
		"/departments/add/":        GetDepartmentForAdd,

		"/api/departments":             GetDepartmentsAll,
		"/api/departments/{id}":        GetDepartmentAll,
		"/api/departments/{id}/update": GetDepartment,
		"/api/departments/add/":        GetNothing,

		// Activity
		"/activities":             GetActivitiesAll,
		"/activities/{id}":        GetActivityAll,
		"/activities/{id}/update": GetActivityForUpdate,
		"/activities/add/":        GetActivityForAdd,

		"/api/activities":             GetActivitiesAll,
		"/api/activities/{id}":        GetActivityAll,
		"/api/activities/{id}/update": GetActivityForUpdate,
		"/api/activities/add/":        GetActivityForAdd,

		// Offices
		"/offices":             GetOfficesAll,
		"/offices/{id}":        GetOfficeAll,
		"/offices/{id}/update": GetOfficeForUpdate,
		"/offices/add/":        GetOfficeForAdd,

		"/api/offices":             GetOfficesAll,
		"/api/offices/{id}":        GetOfficeAll,
		"/api/offices/{id}/update": GetOffice,
		"/api/offices/add/":        GetNothing,

		// Administratives
		"/administratives":             GetAdministrativesAll,
		"/administratives/{id}":        GetAdministrativeAll,
		"/administratives/{id}/update": GetAdministrativeForUpdate,
		"/administratives/add/":        GetAdministrativeForAdd,

		"/api/administratives":             GetAdministrativesAll,
		"/api/administratives/{id}":        GetAdministrativeAll,
		"/api/administratives/{id}/update": GetAdministrative,
		"/api/administratives/add/":        GetNothing,

		// Documents
		"/documents":              GetDocumentsAll,
		"/documents/{id}":         GetDocumentAll,
		"/documents/{id}/update":  GetDocumentForUpdate,
		"/documents/{id}/execute": GetDocumentExecute,
		"/documents/add/":         GetDocumentForAdd,

		"/api/documents":             GetDocumentsAll,
		"/api/documents/{id}":        GetDocumentAll,
		"/api/documents/{id}/update": GetDocument,
		"/api/documents/add/":        GetNothing,

		// Jobs

		"/jobs":                       GetJobs,
		"/jobs/{id}":                  GetJob,
		"/jobs/{id}/files/{filename}": GetFile,

		"/api/jobs/{id}": GetJob,
		"/api/jobs/add/": GetNothing,
	}

	Post map[string]PostFn = map[string]PostFn{
		// Teacher
		"/teachers/{id}/update": UpdateTeacher,
		"/teachers/{id}/delete": DeleteTeacher,
		"/teachers/add/":        AddTeacher,

		"/api/teachers/add":         AddTeacher,
		"/api/teachers/{id}/update": UpdateTeacher,
		"/api/teachers/{id}/delete": DeleteTeacher,
		"/api/teachers/add/":        AddTeacher,

		// Student
		"/students/{id}/update": UpdateStudent,
		"/students/{id}/delete": DeleteStudent,
		"/students/add/":        AddStudent,

		"/api/students/add":         AddStudent,
		"/api/students/{id}/update": UpdateStudent,
		"/api/students/{id}/delete": DeleteStudent,
		"/api/students/add/":        AddStudent,

		// Classes
		"/classes/{id}/update": UpdateClass,
		"/classes/{id}/delete": DeleteClass,
		"/classes/add/":        AddClass,

		"/api/classes/{id}/update": UpdateClass,
		"/api/classes/{id}/delete": DeleteClass,
		"/api/classes/add/":        AddClass,

		// Subjects
		"/subjects/{id}/update": UpdateSubject,
		"/subjects/{id}/delete": DeleteSubject,
		"/subjects/add/":        AddSubject,

		"/api/subjects/{id}/update": UpdateSubject,
		"/api/subjects/{id}/delete": DeleteSubject,
		"/api/subjects/add/":        AddSubject,

		// Departments
		"/departments/{id}/update": UpdateDepartment,
		"/departments/{id}/delete": DeleteDepartment,
		"/departments/add/":        AddDepartment,

		"/api/departments/{id}/update": UpdateDepartment,
		"/api/departments/{id}/delete": DeleteDepartment,
		"/api/departments/add/":        AddDepartment,

		// Activity
		"/activities/{id}/update": UpdateActivity,
		"/activities/{id}/delete": DeleteActivity,
		"/activities/add/":        AddActivity,

		"/api/activities/{id}/update": UpdateActivity,
		"/api/activities/{id}/delete": DeleteActivity,
		"/api/activities/add/":        AddActivity,

		// Offices
		"/offices/{id}/update": UpdateOffice,
		"/offices/{id}/delete": DeleteOffice,
		"/offices/add/":        AddOffice,

		"/api/offices/{id}/update": UpdateOffice,
		"/api/offices/{id}/delete": DeleteOffice,
		"/api/offices/add/":        AddOffice,

		// Administratives
		"/administratives/{id}/update": UpdateAdministrative,
		"/administratives/{id}/delete": DeleteAdministrative,
		"/administratives/add/":        AddAdministrative,

		"/api/administratives/{id}/update": UpdateAdministrative,
		"/api/administratives/{id}/delete": DeleteAdministrative,
		"/api/administratives/add/":        AddAdministrative,

		// Documents
		"/documents/{id}/update": UpdateDocument,
		"/documents/{id}/delete": DeleteDocument,
		"/documents/add/":        AddDocument,

		"/api/documents/{id}/update": UpdateDocument,
		"/api/documents/{id}/delete": DeleteDocument,
		"/api/documents/add/":        AddDocument,

		// Jobs

		"/jobs/{id}/delete": DeleteJob,

		"/api/jobs/{id}/update": UpdateJob,
		"/api/jobs/{id}/delete": DeleteJob,
	}
)

func MapModels(models []interface{}, handlers map[string]string) {
	for _, model := range models {
		name := inflection.Plural(strings.ToLower(modelName(model)))
		for p, action := range map[string]string{
			"":            "GetAll",
			"create":      "Create",
			"{id}":        "Get",
			"{id}/udpate": "Update",
		} {
			getFns[path.Join("/", name, p)] = reflect.ValueOf(model).MethodByName(action).Interface().(func(map[string]string) (interface{}, error))
		}
	}
}

func modelName(s interface{}) string {
	if t := reflect.TypeOf(s); t.Kind() == reflect.Ptr {
		return t.Elem().Name()
	} else {
		return t.Name()
	}
}
