<?php

/**
 * Ausgabe von Schlafdaten
 *
 * Gespeichert als Posts (Post-Type appsleepweek)
 *
 * @author  Hamid Mergan <hamid.mergan@th-luebeck.de>

 */

class Trainingssystem_Plugin_Module_App_Data
{
    public function coachOutputAppDataList($atts)
    {
        $title = "Schlafeffizienz-Übersicht";
        if (isset($atts['titel'])) { // Allow empty title here!
            $title = $atts['titel'];
        }

        $type = null;
        if (isset($atts['type']) && trim($atts['type']) != "") {
            $type = $atts['type'];
        }
        $posts = get_posts(
            [
                'author' => Trainingssystem_Plugin_Public::getTrainingUser(),
                'post_type' => $type,
                'numberposts' => -1,
            ]
        );
        $sleepweeks = [];
        foreach ($posts as $post) {
            $sleepweeks[] = array_merge(
                json_decode($post->post_content, true)
            );
        }
        $twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

        if (is_null($type)) {
            return $twig->render("coach-output-app-data/coach-output-app-data-list-error.html");
        } else {

            return $twig->render("coach-output-app-data/coach-output-app-data-list.html", [
                "sleepweeks" => $sleepweeks,
                "title" => $title,
            ]);
        }
    }

    public function coachOutputAppDataChart($atts)
    {
        $arrayAllLimits = array('Alle Wochen');

        $title = "Schlafeffizienz-Übersicht";
        if (isset($atts['titel'])) { // Allow empty title here!
            $title = $atts['titel'];
        }

        $type = null;
        if (isset($atts['type']) && trim($atts['type']) != "") {
            $type = $atts['type'];
        }

        $mode = 'line';
        if (isset($atts['mode']) && trim($atts['mode']) == 'bar') {
            $mode = $atts['mode'];
        }

        $posts = get_posts(
            [
                'author' => Trainingssystem_Plugin_Public::getTrainingUser(),
                'post_type' => $type,
                'numberposts' => -1,
            ]
        );

        $sleepweeks = [];
        $sleepweeksSorted = [];

        foreach ($posts as $post) {
            $sleepweeks[] = array_merge(
                json_decode($post->post_content, true)
            );
            $sleepweeksSorted[] = array_merge(
                json_decode($post->post_content, true)
            );
        }

        usort($sleepweeksSorted, array($this, "cmp"));

        $twig = Trainingssystem_Plugin_Twig::getInstance()->twig;

        if (is_null($type)) {
            return $twig->render("coach-output-app-data/coach-output-app-data-list-error.html");
        } else {

            return $twig->render("coach-output-app-data/coach-output-app-data-chart.html", [
                "sleepweeks" => $sleepweeks,
                "sleepweeksSorted" => $sleepweeksSorted,
                "title" => $title,
                "arrayAllLimits" => $arrayAllLimits,
                "mode" => $mode,
            ]);
        }
    }

    /**
     * compare to sort week by toBed
     */
    public function cmp($a, $b)
    {
        return strtotime($a['days'][count($a['days']) - 1]['toBed']) - strtotime($b['days'][count($b['days']) - 1]['toBed']);
    }


    /**
     * Anzeige der App-Daten als Liste oder Chart
     */
    public function isleepOutputAppData($atts)
    {
        $twig = Trainingssystem_Plugin_Twig::getInstance()->twig;
        $usermodus = false;
            $uid = get_current_user_id();
            $selectui = '' . get_user_meta(wp_get_current_user()->ID, 'coach_select_user', true);
            if ($selectui != '') {
                $uid = $selectui;
                $usermodus = true;
            }

        $nodata = 1;
        $sleepEffData = [];
        $formfieldAndData = [];
        $allFormsSortedMp = [];
        $allFormsSortedAp = [];
        $ids = new stdClass();
        $title = "Schlafeffizienz-Übersicht";
        if (isset($atts['titel'])) { // Allow empty title here!
            $title = $atts['titel'];
        }

        $trainingid = null;
        if (isset($atts['trainingid']) && trim($atts['trainingid']) != "") {
            $trainingid = $atts['trainingid'];
        }

        $amountformsmp = null;
        if (isset($atts['amountformsmp']) && trim($atts['amountformsmp']) != "") {
            $amountformsmp = $atts['amountformsmp'];
        }

        $amountformsap = null;
        if (isset($atts['amountformsap']) && trim($atts['amountformsap']) != "") {
            $amountformsap = $atts['amountformsap'];
        }

        $getup = null;
        if (isset($atts['getup']) && trim($atts['getup']) != "") {
            $getup = $atts['getup'];
        }
        $dur = null;
        if (isset($atts['dur']) && trim($atts['dur']) != "") {
            $dur = $atts['dur'];
        }
        $tobed = null;
        if (isset($atts['tobed']) && trim($atts['tobed']) != "") {
            $tobed = $atts['tobed'];
        }
        $asleep = null;
        if (isset($atts['asleep']) && trim($atts['asleep']) != "") {
            $asleep = $atts['asleep'];
        }
        $awake = null;
        if (isset($atts['awake']) && trim($atts['awake']) != "") {
            $awake = $atts['awake'];
        }
        $awakenight = null;
        if (isset($atts['awakenight']) && trim($atts['awakenight']) != "") {
            $awakenight = $atts['awakenight'];
        }
        $nap = null;
        if (isset($atts['nap']) && trim($atts['nap']) != "") {
            $nap = $atts['nap'];
        }
        $amountsites = null;
        if (isset($atts['amountsites']) && trim($atts['amountsites']) != "") {
            $amountsites = $atts['amountsites'];
        }

        $thisTraining = Trainingssystem_Plugin_Database::getInstance()->TrainingDao->getTrainingById(intval($trainingid));
        $lektionsliste = $thisTraining->getLektionsliste();
        $ids->$trainingid = [];
        foreach ($lektionsliste as $lektion) {
            array_push($ids->$trainingid, $lektion->getId());
        }
        $formids = $this::filterForms($ids);

        $output = $this->getFormField(implode(",", $formids));

        $outputMp = array_slice($output, 0, intval($amountformsmp) * intval($amountsites));
        $outputAp = array_slice($output, intval($amountformsmp) * intval($amountsites));

        for ($i = 0; $i < $amountsites; $i++) {
            $outputTemp = array_slice($outputMp, $i * intval($amountformsmp), intval($amountformsmp));
            array_push($allFormsSortedMp, $outputTemp);
            $outputTemp = "";
        }

        for ($i = 0; $i < $amountsites; $i++) {
            $outputTemp = array_slice($outputAp, $i * intval($amountformsap), intval($amountformsap));
            array_push($allFormsSortedAp, $outputTemp);
            $outputTemp = "";
        }

  


        $formdatas = $this->getFormDatas(implode(",", $this->extractIDs($output)), $uid);


        foreach ($allFormsSortedMp as $key => $siteForms) {
            $tempObj = new stdClass();


            $tempObj->getup = $siteForms[$getup - 1];
            if($this->findIndexInFormdatas($siteForms[$getup - 1]->ID,$formdatas) != -1){
                $tempObj->getupData = $formdatas[$this->findIndexInFormdatas($siteForms[$getup - 1]->ID,$formdatas)];
            }else {
                $tempObj->getupData = null;
            }

            $tempObj->dur = $siteForms[$dur - 1];
            if($this->findIndexInFormdatas($siteForms[$dur - 1]->ID,$formdatas) != -1){
                $tempObj->durData = $formdatas[$this->findIndexInFormdatas($siteForms[$dur - 1]->ID,$formdatas)];
            }else {
                $tempObj->durData = null;
            }

            $tempObj->tobed = $siteForms[$tobed - 1];
            if($this->findIndexInFormdatas($siteForms[$tobed - 1]->ID,$formdatas) != -1){
                $tempObj->tobedData = $formdatas[$this->findIndexInFormdatas($siteForms[$tobed - 1]->ID,$formdatas)];
            }else {
                $tempObj->tobedData = null;
            }

            $tempObj->dateMp = $siteForms[1];
            if($this->findIndexInFormdatas($siteForms[1]->ID,$formdatas) != -1){
                $tempObj->dateMpData = $formdatas[$this->findIndexInFormdatas($siteForms[1]->ID,$formdatas)];
            }else {
                $tempObj->dateMpData = null;
            }
            
            $tempObj->asleep = $siteForms[$asleep - 1];
            if($this->findIndexInFormdatas($siteForms[$asleep - 1]->ID,$formdatas) != -1){
                $tempObj->asleepData = $formdatas[$this->findIndexInFormdatas($siteForms[$asleep - 1]->ID,$formdatas)];
            }else {
                $tempObj->asleepData = null;
            }

            $tempObj->awake = $siteForms[$awake - 1];
            if($this->findIndexInFormdatas($siteForms[$awake - 1]->ID,$formdatas) != -1){
                $tempObj->awakeData = $formdatas[$this->findIndexInFormdatas($siteForms[$awake - 1]->ID,$formdatas)];
            }else {
                $tempObj->awakeData = null;
            }

            $tempObj->awakenight = $siteForms[$awakenight - 1];
            if($this->findIndexInFormdatas($siteForms[$awakenight - 1]->ID,$formdatas) != -1){
                $tempObj->awakenightData = $formdatas[$this->findIndexInFormdatas($siteForms[$awakenight - 1]->ID,$formdatas)];
            }else {
                $tempObj->awakenightData = null;
            }

            $tempObj->nap = $allFormsSortedAp[$key][$nap-1];
            if($this->findIndexInFormdatas($allFormsSortedAp[$key][$nap-1]->ID,$formdatas) != -1){
                $tempObj->napData = $formdatas[$this->findIndexInFormdatas($allFormsSortedAp[$key][$nap-1]->ID,$formdatas)];
            }else {
                $tempObj->napData = null;
            }

            $tempObj->dateAp = $allFormsSortedAp[$key][1];
            if($this->findIndexInFormdatas( $allFormsSortedAp[$key][1]->ID,$formdatas) != -1){
                $tempObj->dateApData = $formdatas[$this->findIndexInFormdatas( $allFormsSortedAp[$key][1]->ID,$formdatas)];
            }else {
                $tempObj->dateApData = null;
            }

            $tempObj->apAtt = $allFormsSortedAp[$key][2];
            if($this->findIndexInFormdatas( $allFormsSortedAp[$key][2]->ID,$formdatas) != -1){
                $tempObj->apAttData = $formdatas[$this->findIndexInFormdatas( $allFormsSortedAp[$key][2]->ID,$formdatas)];
            }else {
                $tempObj->apAttData = null;
            }


            array_push($formfieldAndData, $tempObj);
        }

        foreach ($formfieldAndData as $key => $value) {
            $tempObj = new stdClass();
            if (
                isset($value->durData) && !is_null($value->durData) &&
                isset($value->apAttData) && !is_null($value->apAttData) &&
                isset($value->tobedData) && !is_null($value->tobedData) &&
                isset($value->getupData) && !is_null($value->getupData)
            ) {
                $tempObj->status = "11";
                $tempObj->tobedData = $value->tobedData->data;
                $tempObj->getupData = $value->getupData->data;
                $tempObj->durData = $value->durData->data;
                $tempObj->dateApData = $value->dateApData->data;
                $tempObj->dateMpData = $value->dateMpData->data;
                $tempObj->apAttData = $value->apAttData->data;
                $tempObj->asleepData = $value->asleepData->data;
                if( !is_null($value->awakenightData) ){
                    $tempObj->awakenightData = $value->awakenightData->data;
                }else{
                    $tempObj->awakenightData = "-";
                }
                if( !is_null($value->awakeData) ){
                    $tempObj->awakeData = $value->awakeData->data;
                }else{
                    $tempObj->awakeData = "-";
                }
                if( !is_null($value->napData) ){
                    $tempObj->napData = $value->napData->data;
                }else{
                    $tempObj->napData = "-";
                }



                sscanf($tempObj->durData, "%d:%d", $hours, $minutes);
                $time_seconds_dur = $hours * 3600 + $minutes * 60;
                $dateTobed = new DateTime($tempObj->dateApData);
                $timeToBed = new DateTime($tempObj->tobedData);
                $dateGetup = new DateTime($tempObj->dateMpData);
                $timeGetup = new DateTime($tempObj->getupData);
                //$dateTobed->setTime($timeToBed->format('H'), $timeToBed->format('i'));
                $dateTobed = $timeToBed;
                $dateGetup->setTime($timeGetup->format('H'), $timeGetup->format('i'));
                $difference_in_seconds = abs($dateTobed->format('U') - $dateGetup->format('U'));
                $sleepEff = round(($time_seconds_dur * 100) / $difference_in_seconds);
                $tempObj->sleepEff = ($sleepEff);
                array_push($sleepEffData, $tempObj);
            } else if (
                isset($value->durData) && !is_null($value->durData) &&
                !(isset($value->apAttData)) && is_null($value->apAttData) &&
                isset($value->tobedData) && !is_null($value->tobedData) &&
                isset($value->getupData) && !is_null($value->getupData)
            ) {
                $tempObj->status = "10";
                $tempObj->tobedData = $value->tobedData->data;
                $tempObj->getupData = $value->getupData->data;
                $tempObj->durData = $value->durData->data;
                $tempObj->dateApData = $value->dateApData->data;
                $tempObj->dateMpData = $value->dateMpData->data;
                $tempObj->asleepData = $value->asleepData->data;
                if( !is_null($value->awakenightData) ){
                    $tempObj->awakenightData = $value->awakenightData->data;
                }else{
                    $tempObj->awakenightData = "-";
                }
                if( !is_null($value->awakeData) ){
                    $tempObj->awakeData = $value->awakeData->data;
                }else{
                    $tempObj->awakeData = "-";
                }
                if( !is_null($value->napData) ){
                    $tempObj->napData = $value->napData->data;
                }else{
                    $tempObj->napData = "-";
                }

                sscanf($tempObj->durData, "%d:%d", $hours, $minutes);
                $time_seconds_dur = $hours * 3600 + $minutes * 60;
                $dateTobed = new DateTime($tempObj->dateApData);
                $timeToBed = new DateTime($tempObj->tobedData);
                $dateGetup = new DateTime($tempObj->dateMpData);
                $timeGetup = new DateTime($tempObj->getupData);
                //$dateTobed->setTime($timeToBed->format('H'), $timeToBed->format('i'));
                $dateTobed = $timeToBed;
                $dateGetup->setTime($timeGetup->format('H'), $timeGetup->format('i'));
                $difference_in_seconds = abs($dateTobed->format('U') - $dateGetup->format('U'));
                $sleepEff = round(($time_seconds_dur * 100) / $difference_in_seconds);
                $tempObj->sleepEff = ($sleepEff);
                array_push($sleepEffData, $tempObj);
            } else if (isset($value->apAttData) && !empty($value->apAttData)) {

                $tempObj->status = "01";
                $tempObj->dateApData = $value->dateApData->data;
                $tempObj->dateMpData = $value->dateMpData->data;
                $tempObj->apAttData = $value->apAttData->data;
                
                array_push($sleepEffData, $tempObj);
            } else {
                    $tempObj->status = "00";
                    $tempObj->dateApData = $value->dateApData->data;
                    $tempObj->dateMpData = $value->dateMpData->data;

                    array_push($sleepEffData, $tempObj);
            }
            $tempObj = "";
        }

        if (is_null($trainingid) || is_null($amountformsap) || is_null($amountformsmp) || is_null($getup) || is_null($dur) || is_null($tobed) || is_null($amountsites)) {
            return $twig->render("isleep-output-app-data/isleep-output-app-data-error.html");
        } else {

            $avgSleepEff = [];
            $avgDur = [];
            foreach (range(0, (intval($amountsites)/7)-1) as $iWeek) {
                $sum = 0;
                $sumDur = 0;
                $counter = 0 ;
                $counterDur = 0 ;
                foreach (array_slice($sleepEffData, (($iWeek)*7), 7)
                as $obj) {
                    //calc avg sleep efficiency
                    if (isset($obj->sleepEff)) {
                        $sum = $sum + intval($obj->sleepEff);
                        $counter++;
                    }
                    //calc avg sleep duration
                    if (isset($obj->durData)) {
                        $splitHourMin = explode(":",$obj->durData );
                        $sumDur = $sumDur + (intval($splitHourMin[0])*60) + $splitHourMin[1];
                        $counterDur++;
                    }
                }
                if ($sum != 0) {
                    $avgSleepEff[$iWeek] = round($sum / $counter);
                    $hours = floor(round($sumDur / $counterDur) / 60);
                    $minutes = str_pad((round($sumDur / $counterDur) % 60), 2, "0", STR_PAD_LEFT);
                    $avgDur[$iWeek] = $hours . ":" . $minutes;
                }
            }
            
            return $twig->render("isleep-output-app-data/isleep-output-app-data.html", [
                "trainingid" => $trainingid,
                "title" => $title,
                "thisTraining" => $thisTraining,
                "formids" => $formids,
                "amountformsmp" => $amountformsmp,
                "amountformsap" => $amountformsap,
                "getup" => $getup,
                "dur" => $dur,
                "tobed" => $tobed,
                "amountsites" => $amountsites,
                "sleepEffData" => $sleepEffData,
                "nodata" => $nodata,
                "avgSleepEff" => $avgSleepEff,
                "avgDur" => $avgDur,
            ]);
                
            
        }
    }

    public function timeToSeconds(string $time): int
    {
        $arr = explode(':', $time);
        if (count($arr) === 3) {
            return $arr[0] * 3600 + $arr[1] * 60 + $arr[2];
        }
        return $arr[0] * 60 + $arr[1];
    }

    /**
     *
     * Filter Forms by Training and Lektionen
     *
     * @return Form-IDs seperated with ;
     */
    public function filterForms($ids)
    {
        $code = "";
        foreach ($ids as $trainingid => $lektionids) {
            $trainingpost = get_post($trainingid, OBJECT);
            $code .= $trainingpost->post_ecerpt . $trainingpost->post_content;
            $count = 0;
            foreach ($lektionids as $lektionid) {
                if ($count < 2) {
                    $lektionpost = get_post($lektionid, OBJECT);
                    $code .= $lektionpost->post_ecerpt . $lektionpost->post_content;
                    $seitenids = $this::getLektionseiten($lektionid);
                    foreach ($seitenids as $seitenid) {
                        $seitenpost = get_post($seitenid);
                        $code .= $seitenpost->post_ecerpt . $seitenpost->post_content;
                    }
                    $count++;
                }
            }
        }

        $regex = "/\[[\wöäüßÖÄÜ0-9-_?! :.,;\/{}()=\"'…\n\r]+\]?/";
        preg_match_all($regex, $code, $matches);
        $all_shortcodes_list = array();
        $s_index = 0;
        foreach ($matches[0] as $match) {
            if (!$this::startsWith($match, "[/")) { // no closing tags here
                $all_shortcodes_list[$s_index]['original_shortcode'] = $match;
                if (strpos($match, " ") !== false) {
                    $all_shortcodes_list[$s_index]['shortcode_name'] = substr($match, 1, strpos($match, " "));
                    $all_shortcodes_list[$s_index] = array_merge($all_shortcodes_list[$s_index], array_slice(shortcode_parse_atts(substr($match, 1, strlen($match) - 2)), 1));
                } else {
                    $all_shortcodes_list[$s_index]['shortcode_name'] = substr($match, 1, strlen($match) - 2);
                }
                $s_index++;
            }
        }
        $found_ids = array();
        foreach ($all_shortcodes_list as $shortcode) {
            switch (trim($shortcode['shortcode_name'])) {
                case "ts_forms":
                    if (isset($shortcode['id']) && !isset($found_ids[$shortcode['id']])) {
                        $found_ids[$shortcode['id']] = $shortcode['id'];
                    }
                    break;
            }
        }
        return array_values($found_ids);
    }

    /**
     * HELPER
     *
     * Get all the Lektion's Seiten IDs as Array
     *
     * @param Integer Lektion-ID
     * @return Int-Array with Page-IDs
     */
    private static function getLektionseiten($lektionid)
    {
        global $wpdb;
        $dbprefix_seiten = $wpdb->prefix . 'md_trainingsmgr_tranings_seiten';

        $sql = $wpdb->prepare("SELECT seiten_id FROM {$dbprefix_seiten} WHERE lektion_id = %d ORDER BY seiten_index ASC", $lektionid);
        $ids = $wpdb->get_col($sql);

return $ids;
    }

    /**
     * HELPER
     *
     * Determines if a String $haystack starts with $needle
     */
    private static function startsWith($haystack, $needle)
    {
        $length = strlen($needle);
        return (substr($haystack, 0, $length) === $needle);
    }


     /**
     * Returns the amount of formfields
     * 
     * @param int form ids
     * 
     * @return int Amount of formfields
     */
    public function getFormField($formids)
    {
        global $wpdb;
        $table_name_fields = $wpdb->prefix . 'md_trainingsmgr_ts_forms_fields';

        $sql = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name_fields WHERE form_ID IN ($formids) ORDER BY FIELD(form_ID, $formids)"));

        return  $sql;
    }

    public function getFormDatas($fieldids, $uid)
    {
        global $wpdb;

        $table_name_data = $wpdb->prefix . 'md_trainingsmgr_ts_forms_data';

        $sql = $wpdb->prepare("SELECT * FROM $table_name_data WHERE field_ID IN ($fieldids) AND user_ID = %d", $uid);

        $row = $wpdb->get_results($sql);


        if ($row != null) {
            return $row;
        }
        return 0;
    }

    function extractIDs2D($dataArray) {
    
    // Initialize an array to store the 'ID' values
    $ids = array();

    // Iterate through the outer array
    foreach ($dataArray as $innerArray) {
        // Iterate through the inner array
        foreach ($innerArray as $element) {
            // Check if 'ID' exists in the current element
            if (isset($element->ID)) {
                // Add 'ID' value to the array
                $ids[] = $element->ID;
            }
        }
    }

    // Return the resulting array of 'ID' values
    return $ids;
    }

    function extractIDs($dataArray) {
        $ids = array();
    
        foreach ($dataArray as $item) {
            if (isset($item->ID)) {
                $ids[] = $item->ID;
            }
        }
    
        return $ids;
    }

    function findIndexInFormdatas($fieldId, $formdatas) {
        foreach ($formdatas as $index => $formdata) {
            if ($formdata->field_ID == $fieldId) {
                return $index; // Return the index of the match
            }
        }
    
        return -1; // No match found, return -1
    }

}