<script>
    var idmFOTMArgs = {
        "attCodes": {},
        "schools": [],
        "groups": [],
        "tardyComments": {
            "T": {},
            "TE": {},
            "TU": {}
        },
        "appTime": new Date("~[date] ~(f.currenttime)"),
        "browserTime": new Date(),
        "curschoolid": "~(curschoolid)",
        "dateDB": "~[date]",
        "date": (new Date()).toLocaleDateString(),
        "daySchedules": {},
        "prefs": {},
        "userArgs": {},
        "periods": [],
        "logoHTML": "",
        "user": "~[x:username]",
        "usersdcid": "~[x:users_dcid]",
        "dailyCICO": {
            "time_in": "~(JSFieldParam;[attendance_time]time_in)".slice(0,-2),
            "time_out": "~(JSFieldParam;[attendance_time]time_out)".slice(0,-2),
            "attendanceid": "~(JSFieldParam;[attendance_time]attendanceid)".slice(0,-2)
        },
        "devMode": false,
        "kioskInstalled": false,
        "isoFormat": function(dateObj) {
            let year = String(dateObj.getFullYear())
            let month = String(dateObj.getMonth()+1)
            if (month < 10) {
                month = month.padStart(2, "0")
            }
            let day = String(dateObj.getDate())
            if (day < 10) {
                day = day.padStart(2, "0")
            }

            return `${year}-${month}-${day}`
        }
    }

    ~[tlist_sql;select sysdate from dual;]idmFOTMArgs.dbTime = new Date("~(sysdate)")[/tlist_sql]
    
    idmFOTMArgs.hourDiffApp = Math.round((idmFOTMArgs.browserTime-idmFOTMArgs.appTime)/36e5)
    idmFOTMArgs.hourDiffDB = Math.round((idmFOTMArgs.browserTime-idmFOTMArgs.dbTime)/36e5)

    idmFOTMArgs.isoDate = idmFOTMArgs.isoFormat(idmFOTMArgs.browserTime)
    
    ~[tlist_sql;
        select
            regexp_replace(prefs.name, chr(94) || 'idm_', '') name,
            prefs.value
        from
            prefs
        where
            prefs.name like 'idm%'
            and (
                prefs.name like '%-S~(curschoolid)'
                or prefs.name not like '%-S%'
                or ~(curschoolid) = 0
            )
        order by
            prefs.name
    ;]
        idmFOTMArgs.prefs["~(prefName)"] = "~(prefValue;json)"
    [/tlist_sql]

    let idm_overrideExceptions = ["attendanceMode-S~(curschoolid)","termLength-S~(curschoolid)","exceptionOverlapPeriods-S~(curschoolid)"]
    let idm_alwaysExceptions = ["exceptionOverlapPeriods-S~(curschoolid)"]
    let idm_commentRegex = /^tardy.*Comment(-\d{1,2}|Maximum)?(-S~(curschoolid))?$/
    let idm_specificOverrides = {
        "exceptionMultiSectionCourses-S~(curschoolid)": "exceptionMultiSectionOverride-S~(curschoolid)"
    }
    
    //Iterate through all of the prefs
    for (const [pref, value] of Object.entries(idmFOTMArgs.prefs)) {
        //Apply the DO settings by default
        if (!pref.includes("-S~(curschoolid)")) {
            idmFOTMArgs[pref] = value
        } else {
            let districtPref = pref.replace("-S~(curschoolid)", "")
            let overridePref = pref.replace("-S~(curschoolid)", "Override-S~(curschoolid)")
            if (idm_commentRegex.test(pref)) {overridePref = "tardyCommentOverride-S~(curschoolid)"}
            if (idm_specificOverrides[pref]) {overridePref = idm_specificOverrides[pref]}
            //If the school is allowed to override or the pref should always be allowed
            if (idmFOTMArgs.prefs.schoolOverride == "1" || idm_overrideExceptions.includes(pref)) {
                //If the setting is overridden or there is always an override
                if (idmFOTMArgs.prefs[overridePref] == "1" || idm_alwaysExceptions.includes(pref)) {
                    //Overwrite the district setting with the school setting
                    idmFOTMArgs[districtPref] = idmFOTMArgs.prefs[pref]
                }
            }
        }
    }

    let numberFields = ["tardyCommentMaximum", "tardyExcusedCommentMaximum", "tardyUnexcusedCommentMaximum", "kioskDurationWelcome", "kioskDurationError", "kioskDenyRecentMinutes"]
    numberFields.forEach(function(field) {
        idmFOTMArgs[field] = parseInt(idmFOTMArgs[field])
    })
    let multipleFields = ["exceptionOverlapPeriods", "exceptionMultiSectionCourses", "kioskPopupInformation", "kioskDenialReasons"]
    multipleFields.forEach(function(field) {
        if (undefined !== idmFOTMArgs[field]) {
            let fieldArr = idmFOTMArgs[field].split(",")
            idmFOTMArgs[field] = fieldArr.map(function(v) {
                return v.trim()
            }).filter(function(v) {
                return v != ""
            })
        }
    })

    for (const [pref, value] of Object.entries(idmFOTMArgs)) {
        if (idm_commentRegex.test(pref)) {
            let details = pref.split("Comment")
            if (details.length == 2) {
                let type = "T"
                if (details[0] == "tardyExcused") {type = "TE"}
                if (details[0] == "tardyUnexcused") {type = "TU"}
                idmFOTMArgs.tardyComments[type][details[1].replace("-","")] = value
            }
        }
    }

    ~[tlist_sql;
        select
            attendance_code.schoolid,
            attendance_code.id,
            attendance_code.presence_status_cd,
            nvl((select json_arrayagg(code_entity.external_name returning clob) from code_entity join att_code_code_entity on code_entity.id = att_code_code_entity.code_entityid where att_code_code_entity.attendance_codeid = attendance_code.id), chr(91) || chr(93)) codeCategories,
            nvl(u_identimetrics_atc_x.clockinoutplan, 0) clockInOutPlan,
            nvl(u_identimetrics_atc_x.useforprinting, 0) useForPrinting,
            attendance_code.att_code,
            nvl(attendance_code.att_code, attendance_code.description),
            attendance_code.description,
            '(' || attendance_code.att_code || ') ' || attendance_code.description label,
            u_identimetrics_atc_x.TotalCountonHallPass,
            u_identimetrics_atc_x.PresetCommentonHallPass,
            u_identimetrics_atc_x.TardyType,
            u_identimetrics_atc_x.useInKioskMode,
            u_identimetrics_atc_x.denyEntryKioskMode,
            nvl(u_identimetrics_atc_x.successAlertKioskMode, 'welcome'),
            u_identimetrics_atc_x.exceptionNoClass
        from
            attendance_code
            left join u_identimetrics_atc_x on attendance_code.dcid = u_identimetrics_atc_x.attendance_codedcid
        where
            attendance_code.yearid = ~(curyearid)
            --and attendance_code.schoolid = ~(curschoolid)
            --and attendance_code.calculate_ada_yn = 1
        order by
            attendance_code.sortorder
    ;]
        if (!idmFOTMArgs.attCodes["~(schoolid;json)"]) {
            idmFOTMArgs.attCodes["~(schoolid;json)"] = []
        }
        idmFOTMArgs.attCodes["~(schoolid;json)"].push({
            "schoolid": "~(schoolid;json)",
            "id": "~(id;json)",
            "presence_status_cd": "~(presence_status_cd;json)",
            "codeCategories": ~(codeCategories),
            "clockInOutPlan": "~(clockInOutPlan;json)",
            "useForPrinting": "~(useForPrinting;json)",
            "att_code": "~(att_code;json)",
            "att_codeKey": "~(att_codeKey;json)",
            "description": "~(description;json)",
            "label": "~(label;json)",
            "totalCountOnHallPass": "~(totalCountOnHallPass;json)",
            "presetCommentonHallPass": "~(presetCommentonHallPass;json)",
            "tardyType": "~(TardyType;json)",
            "useInKioskMode": "~(useInKioskMode;json)",
            "denyEntryKioskMode": "~(denyEntryKioskMode;json)",
            "successAlertKioskMode": "~(successAlertKioskMode;json)",
            "exceptionNoClass": "~(exceptionNoClass;json)",
            "isTardyCode": false,
            "isUnexcusedTardyCode": false
        })
    [/tlist_sql]

    for ([key, value] of Object.entries(idmFOTMArgs.attCodes)) {
        if (value) {
            value.forEach(function(attCode) {
                attCode.codeCategories.forEach(function(category) {
                    if (category.toLowerCase().includes("tardy")) {
                        attCode.isTardyCode = true
                    } else if (category.toLowerCase().includes("unexcused") && attCode.presence_status_cd == "Present") {
                        attCode.isUnexcusedTardyCode = true
                    }
                })
            })
        }
    }
    
    ~[tlist_sql;
        select
            to_char(calendar_day.date_value, 'YYYY-MM-DD') date_value,
            to_char(to_date(bell_schedule_items.daily_time_in_default, 'sssss'),'HH24' || CHR(58) || 'MI') daystart,
            to_char(to_date(bell_schedule_items.daily_time_out_default, 'sssss'),'HH24' || CHR(58) || 'MI') dayend,
            nvl(periodSchedule.periodSchedule, chr(91) || chr(93)) periodSchedule
        from
            calendar_day
            left join bell_schedule_items on calendar_day.bell_schedule_id = bell_schedule_items.bell_schedule_id
                and bell_schedule_items.daily_attendance_code = 1
            join terms on calendar_day.schoolid = terms.schoolid
                and terms.isyearrec = 1
                and calendar_day.date_value between terms.firstday and terms.lastday
            left join (
                select
                    calendar_day.id calendar_dayid,
                    json_arrayagg(
                        json_object(
                            'period_number' value to_char(period.period_number),
                            period.abbreviation,
                            period.name,
                            'description' value period.name || ' (' || period.abbreviation || ')',
                            'start_time' value to_char(to_date(bell_schedule_items.start_time, 'sssss'),'HH24' || CHR(58) || 'MI'),
                            'end_time' value to_char(to_date(bell_schedule_items.end_time, 'sssss'),'HH24' || CHR(58) || 'MI')
                        ) order by bell_schedule_items.start_time, bell_schedule_items.end_time, period.period_number returning clob
                    ) periodSchedule
                from
                    period
                    join bell_schedule_items on period.id = bell_schedule_items.period_id
                    join calendar_day on bell_schedule_items.bell_schedule_id = calendar_day.bell_schedule_id
                where
                    period.year_id = ~(curyearid)
                    and period.schoolid = ~(curschoolid)
                group by
                    calendar_day.id
            ) periodSchedule on calendar_day.id = periodSchedule.calendar_dayid
        where
            calendar_day.schoolid = ~(curschoolid)
            and terms.yearid = ~(curyearid)
            and calendar_day.date_value in (trunc(sysdate)-2, trunc(sysdate)-1, trunc(sysdate), trunc(sysdate)+1, trunc(sysdate)+2)
        order by
            calendar_day.date_value
    ;]
        idmFOTMArgs.daySchedules["~(date_value)"] = {
            "daystart": "~(daystart)",
            "dayend": "~(dayend)",
            "periodSchedule": ~(periodSchedule)
        }
    [/tlist_sql]
    
    idmFOTMArgs.currentDay = idmFOTMArgs.daySchedules[idmFOTMArgs.isoDate]

    idmFOTMArgs.periods = idmFOTMArgs.currentDay.periodSchedule
    idmFOTMArgs.periods.forEach(function(period) {
        let startTime = new Date(`${idmFOTMArgs.isoDate}T${period.start_time}:00`)
        let endTime = new Date(`${idmFOTMArgs.isoDate}T${period.end_time}:00`)
        period.start_timeMS = startTime.getTime()
        period.end_timeMS = endTime.getTime()
        period.runTime = endTime-startTime
    })

    function idmFindStartEndPeriods(periodMode) {
        let minTime = (new Date(`${idmFOTMArgs.isoDate}T23:59:59`)).getTime()
        let maxTime = (new Date(`${idmFOTMArgs.isoDate}T00:00:00`)).getTime()
        let minPeriodNumber = 999999
        let maxPeriodNumber = 0
        let minPeriod
        let maxPeriod
        idmFOTMArgs.currentDay.periodSchedule.forEach(function(period) {
            if (period.start_timeMS < minTime) {
                minTime = period.start_timeMS
                if (periodMode == "time") {minPeriod = period}
            }
            if (period.end_timeMS > maxTime) {
                maxTime = period.end_timeMS
                if (periodMode == "time") {maxPeriod = period}
            }
            if (Number(period.period_number) < minPeriodNumber) {
                minPeriodNumber = Number(period.period_number)
                if (periodMode == "period") {minPeriod = period}
            }
            if (Number(period.period_number) > maxPeriodNumber) {
                maxPeriodNumber = Number(period.period_number)
                if (periodMode == "period") {maxPeriod = period}
            }
        })

        if (minPeriod) {idmFOTMArgs.currentDay.daystart = minPeriod.start_time}
        if (maxPeriod) {idmFOTMArgs.currentDay.dayend = maxPeriod.end_time}
    }

    ~[if#att_recordmodedaily.~[displayprefyearschool:att_recordmodedaily]=1]
    [else#att_recordmodedaily]
        idmFindStartEndPeriods("time")
    [/if#att_recordmodedaily]

    if (idmFOTMArgs.currentDay.daystart == "" && idmFOTMArgs.currentDay.periodSchedule.length > 0) {
        idmFindStartEndPeriods("time")
    }

    idmFOTMArgs.daystart = idmFOTMArgs.currentDay.daystart
    idmFOTMArgs.dayend = idmFOTMArgs.currentDay.dayend
    idmFOTMArgs.daystartTime = new Date(`${idmFOTMArgs.isoDate}T${idmFOTMArgs.daystart}:00`)
    idmFOTMArgs.dayendTime = new Date(`${idmFOTMArgs.isoDate}T${idmFOTMArgs.dayend}:00`)

    idmFOTMArgs.schoolStudents = []
    idmFOTMArgs.currentSchoolStudents = []
    idmFOTMArgs.students = []
    ~[tlist_sql;
        select
            students.schoolid,
            json_arrayagg(
                json_array(
                    students.dcid,
                    students.lastfirst,
                    students.grade_level,
                    students.enroll_status,
                    students.id,
                    students.student_number,
                    students.lunch_id,
                    students.state_studentnumber
                    returning clob
                ) order by lastfirst returning clob 
            ) studentList
        from
            students
        group by
            students.schoolid
    ;]
        idmFOTMArgs.schoolStudents.push({
            "schoolid": "~(schoolid;json)",
            "studentList": "~(studentList;json)"
        })
    [/tlist_sql]

    idmFOTMArgs.schoolStudents.forEach(function(school) {
        try {
            school.studentList = JSON.parse(school.studentList)
        }
        catch {
            school.studentList = []
        }
        school.studentList.forEach(function(student) {
            let studentModel = {
                "schoolid": school.schoolid,
                "studentsdcid": String(student[0]),
                "lastfirst": student[1],
                "grade_level": String(student[2]),
                "enroll_status": student[3],
                "studentid": String(student[4]),
                "student_number": String(Number(student[5])),
                "studentIdentifier": String(Number(student[4+Number(idmFOTMArgs.scanWithStudentNumber)]))
            }
            idmFOTMArgs.students.push(studentModel)
            if (idmFOTMArgs.curschoolid == school.schoolid && studentModel.enroll_status == 0) {
                idmFOTMArgs.currentSchoolStudents.push(studentModel)
            }
        })
    })

    ~[tlist_sql;
        select
            defaultCode
        from
            u_identimetrics_att_fotm_user
        where
            u_identimetrics_att_fotm_user.usersdcid = ~[x:users_dcid]
    ;]
        if ("~(defaultCode;json)" != "") {
            idmFOTMArgs.userArgs.defaultAttendanceCodeSchool = idmFOTMArgs.defaultAttendanceCode
            idmFOTMArgs.userArgs.defaultAttendanceCode = "~(defaultCode;json)"
        }
    [/tlist_sql]

    if (idmFOTMArgs.shouldPrintLogo == "1" && idmFOTMArgs.logoName != "") {
        idmFOTMArgs.logoHTML = `<img src="/images/${idmFOTMArgs.logoName}" class="idMLogoImage">`
    }

    ~[tlist_sql;
        select
            schools.school_number,
            schools.name
        from
            schools
        order by
            schools.sortorder
    ;]
        idmFOTMArgs.schools.push({
            "schoolid": "~(school_number;json)",
            "name": "~(name;json)"
        })
    [/tlist_sql]

    ~[tlist_sql;
        select
            gen.name,
            gen.id
        from
            gen
        where
            gen.cat = 'groups'
        order by
            gen.id
    ;]
    
        idmFOTMArgs.groups.push({
            "name": "~(name;json)",
            "number": "~(number;json)"
        })
    [/tlist_sql]

    require.config({
        urlArgs: "v=~[tlist_sql; select version from plugindef where name = 'idM AutoTardy';]~(v)[/tlist_sql]"
    })
</script>

~[wc:idM_autoTardyPlus_args]
~[wc:idM_autoTardy_auth]