<?php
/**
 * Created by PhpStorm.
 * User: vlade
 * Date: 5/23/15
 * Time: 12:43 PM
 */

namespace VGM\WOBundle\Service;

//use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use VGM\WOBundle\Entity\LaborLoop;
use VGM\WOBundle\Entity\NoticeLoop;

class UtilServices
{
    protected $entityManager;

    public function __construct($entityManager) {
        $this->entityManager = $entityManager;
    }

    //Getting dates related methos
    public function getFirstWeekDay($date)
    {
        $dw = date('w', $date->getTimestamp());

        $fd = clone $date;
        $fd->setTime(0, 0, 0);

        if($dw != 3){
            if($dw > 3){
                $fd->modify('-'.($dw - 3).' day');
            }
            if($dw < 3){
                $fd->modify('-'.($dw + 4).' day');
            }
        }

        return $fd;
    }
    public function getLastWeekDay($date)
    {
        $fd = $this->getFirstWeekDay($date);
        $fd->modify('+6 day');

        return $fd;
    }

    //Getting times totals related methos
    public function getWorkerWorkedTimeByDate($worker_id, $date)
    {
        $em = $this->entityManager;

        return $em->getRepository('VGMWOBundle:LaborLoop')
            ->getLoopsSumByWorkerDate($worker_id, $date);
    }
    public function getWorkerWorkedTimeByWeek($worker_id, $date1, $date2)
    {
        $em = $this->entityManager;

        return $em->getRepository('VGMWOBundle:LaborLoop')
            ->getLoopsSumByWorkerWeek($worker_id, $date1, $date2);
    }

    //Closing days related methos
    public function updateAllLoopsTimesBetweenDatesAux($date1, $date2)
    {
        $em = $this->entityManager;

        $workers = $em->getRepository('VGMWOBundle:Worker')->findAll();
        while($date2 >= $date1){
            foreach($workers as $worker){
                $this->updateDayLoopsTimes($worker->getId(), $date2);
            }
            $date2->modify('-1 day');
        }
    }
    public function updateAllWorkerLoopsTimesBetweenDates($worker_id, $date1, $date2)
    {
        $em = $this->entityManager;

        $loops = $em->getRepository('VGMWOBundle:LaborLoop')
            ->getOneLoopPerDayWorkerBetweenDates($worker_id, $date1, $date2);
        foreach($loops as $loop)
            $this->updateDayLoopsTimes($worker_id, $loop->getDate());
    }
    public function updateDayLoopsTimes($worker_id, $date)
    {
        $em = $this->entityManager;

        $loops = $em->getRepository('VGMWOBundle:LaborLoop')
            ->getLoopsByWorkerDate($worker_id, $date);
        $day_time = $em->getRepository('VGMWOBundle:LaborLoop')
            ->getLoopsSumByWorkerDate($worker_id, $date);

        $extra = $day_time - 8;
        if(date('w', $date->getTimestamp()) == 0 || date('w', $date->getTimestamp()) == 6)
            $extra = $day_time;

        for ($i = count($loops) - 1; $i >= 0; $i--) {
            $current_loop = $loops[$i];
            if($extra != 0 ){
                $notice = $current_loop->getNotice();
                if($notice == null){
                    $notice = new NoticeLoop();
                    $notice->setLoop($current_loop);
                    $current_loop->setNotice($notice);
                    $em->persist($notice);
                }
                $notice->setPOvertime($extra > 0);
                $notice->setCOvertime(false);
                $notice->setUOvertime($extra < 0);
                $em->flush($notice);
            }
            else{
                $notice = $current_loop->getNotice();
                if($notice != null){
                    $current_loop->setNotice(null);
                    $em->remove($notice);
                }
            }

            if($current_loop->getTotalTime() >= abs($extra)){
                $current_loop->setPOvertime($extra);
                $extra = 0;
            }
            elseif($extra > 0){
                $current_loop->setPOvertime($current_loop->getTotalTime());
                $extra = $extra - $current_loop->getTotalTime();
            }
            elseif($extra < 0){
                $current_loop->setPOvertime($extra);
                $extra = 0;
            }

            $em->flush();
        }

        /*if($this->isWorkerWeekClosed($worker_id, $date)){
           $this->closeWorkerWeek($worker_id, $date);
        }*/

        /*$now = new \DateTime();
        $ddiff = $now->diff($loop->getDate());

        return "Ok";//$ddiff->d;*/
    }

    //Closing Weeks related methos
    public function isWorkerWeekClosed($worker_id, $date)
    {
        $em = $this->entityManager;

        return $em->getRepository('VGMWOBundle:LaborLoop')
            ->getIfWeekIsClosed($worker_id, $this->getFirstWeekDay($date), $this->getLastWeekDay($date));
    }
    public function closeAllPastWeeksAux($first_cycle_first_day, $date)
    {
        /*first_cycle_first_day: "01/07/2015"
    last_cycle_last_day: "01/20/2015"*/
        $em = $this->entityManager;

        $workers = $em->getRepository('VGMWOBundle:Worker')->findAll();

        $fd = $this->getFirstWeekDay($date);
        $fd->modify('-7 day');

        while($fd >= $first_cycle_first_day){
            foreach($workers as $w){
                $this->closeWorkerWeek($w->getId(), $fd);
            }
            $fd->modify('-7 day');
        }
    }
    public function closeAllPastWeeks($date_from, $date)
    {
        $em = $this->entityManager;

        $workers = $em->getRepository('VGMWOBundle:Worker')->findAll();

        $fd = $this->getFirstWeekDay($date);
        $fd->modify('-7 day');

        while($fd >= $date_from){
            foreach($workers as $w){
                if($this->isWorkerWeekClosed($w->getId(), $fd) == false)
                    $this->closeWorkerWeek($w->getId(), $fd);
            }
            $fd->modify('-7 day');
        }
    }
    public function closeWorkerWeek($worker_id, $date)
    {
        $em = $this->entityManager;

        if($this->getWorkerWorkedTimeByWeek($worker_id, $this->getFirstWeekDay($date),
                $this->getLastWeekDay($date)) > 40){
            $POloops = $em->getRepository('VGMWOBundle:LaborLoop')
                ->getLoopsWithPOvertime($worker_id, $this->getFirstWeekDay($date), $this->getLastWeekDay($date));
            $UOloops = $em->getRepository('VGMWOBundle:LaborLoop')
                ->getLoopsWithUOvertime($worker_id, $this->getFirstWeekDay($date), $this->getLastWeekDay($date));

            for($i = 0; $i < count($POloops); $i++){
                $co = $POloops[$i]->getPOvertime();
                $POloops[$i]->setCOvertime($co > 0 ? $co : 0);
            }

            if(count($POloops) > 0 && count($UOloops)){
                foreach($UOloops as $uoloop){
                    $j = 0;
                    $uo = $uoloop->getPOvertime();
                    while($uo < 0 && $j < count($POloops)){
                        if($POloops[$j]->getCOvertime() > 0){
                            $co = $POloops[$j]->getCOvertime();
                            if(($uo + $co) <= 0){
                                $POloops[$j]->setCOvertime(0);
                                $uo = $uo + $co;
                            }
                            else{
                                $POloops[$j]->setCOvertime($uo + $co);
                                $uo = 0;

                                $notice = $POloops[$j]->getNotice();
                                if($notice == null){
                                    $notice = new NoticeLoop();
                                    $notice->setLoop($POloops[$j]);
                                    $POloops[$j]->setNotice($notice);
                                    $em->persist($notice);
                                }
                                $notice->setPOvertime(true);
                                $notice->setCOvertime(true);
                                $notice->setUOvertime(false);
                                $em->flush($notice);
                            }
                        }
                        $j++;
                    }
                }
            }

            foreach($POloops as $loop){
                $em->flush($loop);
            }

            $loops = $em->getRepository('VGMWOBundle:LaborLoop')
                ->getLoopsByWorkerWeek($worker_id, $this->getFirstWeekDay($date), $this->getLastWeekDay($date));
            foreach($loops as $loop){
                $loop->setWeekClosed(true);
                $notice = $loop->getNotice();
                if($notice != null){
                    if(!$notice->getCOvertime()){
                        $loop->setNotice(null);
                        $em->remove($notice);
                    }
                }
                $em->flush();
            }
        }
        else{
            $loops = $em->getRepository('VGMWOBundle:LaborLoop')
                ->getLoopsByWorkerWeek($worker_id, $this->getFirstWeekDay($date), $this->getLastWeekDay($date));
            foreach($loops as $loop){
                $loop->setWeekClosed(true);
                $loop->setCOvertime(0);
                $em->flush($loop);
            }
        }
    }
} 