module api_modules.classroom_compliance.model;

import ddbc : DataSetReader;
import handy_httpd.components.optional;
import std.json;
import std.datetime;

struct ClassroomComplianceClass {
    const ulong id;
    const ushort number;
    const string schoolYear;
    const ulong userId;
    const string scoreExpression;
    const string scorePeriod;

    static ClassroomComplianceClass parse(DataSetReader r) {
        return ClassroomComplianceClass(
            r.getUlong(1),
            r.getUshort(2),
            r.getString(3),
            r.getUlong(4),
            r.getString(5),
            r.getString(6)
        );
    }
}

struct ClassroomComplianceStudent {
    const ulong id;
    const string name;
    const ulong classId;
    const ushort deskNumber;
    const bool removed;

    static ClassroomComplianceStudent parse(DataSetReader r) {
        return ClassroomComplianceStudent(
            r.getUlong(1),
            r.getString(2),
            r.getUlong(3),
            r.getUshort(4),
            r.getBoolean(5)
        );
    }
}

struct ClassroomComplianceEntry {
    const ulong id;
    const ulong classId;
    const ulong studentId;
    const Date date;
    const ulong createdAt;
    const bool absent;
    const string comment;
    const Optional!bool phoneCompliant;
    const Optional!ubyte behaviorRating;

    static ClassroomComplianceEntry parse(DataSetReader r) {
        Optional!bool phone = !r.isNull(8)
            ? Optional!bool.of(r.getBoolean(8))
            : Optional!bool.empty;
        Optional!ubyte behavior = !r.isNull(9)
            ? Optional!ubyte.of(r.getUbyte(9))
            : Optional!ubyte.empty;

        return ClassroomComplianceEntry(
            r.getUlong(1),
            r.getUlong(2),
            r.getUlong(3),
            r.getDate(4),
            r.getUlong(5),
            r.getBoolean(6),
            r.getString(7),
            phone,
            behavior
        );
    }

    JSONValue toJsonObj() const {
        JSONValue obj = JSONValue.emptyObject;
        obj.object["id"] = JSONValue(id);
        obj.object["classId"] = JSONValue(classId);
        obj.object["studentId"] = JSONValue(studentId);
        obj.object["date"] = JSONValue(date.toISOExtString());
        obj.object["createdAt"] = JSONValue(createdAt);
        obj.object["absent"] = JSONValue(absent);
        obj.object["comment"] = JSONValue(comment);
        if (absent) {
            if (!phoneCompliant.isNull || !behaviorRating.isNull) {
                throw new Exception("Illegal entry state! Absent is true while values are not null!");
            }
            obj.object["phoneCompliant"] = JSONValue(null);
            obj.object["behaviorRating"] = JSONValue(null);
        } else {
            if (phoneCompliant.isNull || behaviorRating.isNull) {
                throw new Exception("Illegal entry state! Absent is false while values are null!");
            }
            obj.object["phoneCompliant"] = JSONValue(phoneCompliant.value);
            obj.object["behaviorRating"] = JSONValue(behaviorRating.value);
        }
        return obj;
    }
}

struct ClassroomComplianceClassNote {
    const ulong id;
    const ulong classId;
    const ulong createdAt;
    const string content;

    static ClassroomComplianceClassNote parse(DataSetReader r) {
        return ClassroomComplianceClassNote(
            r.getUlong(1),
            r.getUlong(2),
            r.getUlong(3),
            r.getString(4)
        );
    }
}
