<?php

namespace Cadoles\PortalBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Cadoles\PortalBundle\Entity\Page;
use Cadoles\PortalBundle\Entity\Pagewidget;
use Cadoles\PortalBundle\Entity\Pagecategory;

class PageRepository extends EntityRepository
{
    // getPagesUser
    // $user            = l'utilisateur en cours
    // $id              = la page en cours que l'on cherche à afficher
    // &$entity         = l'entité de la page à afficher
    // &$pagesuser      = les pages de l'utilisateur
    // &$pages          = les pages système de l'utilistauer
    // &$pagesshared    = les pages partagées pour l'utilisateur
    
    public function getPagesUser($user,$id,&$entity,&$pagesuser,&$pages,&$groupsshared)
    {
        // Profilage
        $roles=($user?$user->getRoles():["ROLE_ANONYME"]);
        $groups=($user?$user->getGroups():[]);


        // CREATION DES PAGES TEMPLATE UTILISATEUR
        if($user) {
            // Initialisation du calcul des templates
            $templatesnotorder=new ArrayCollection();

            // Récupération des templates par rôles
            foreach($roles as $role) {
                $qb = $this->createQueryBuilder("page");
                $qb ->where($qb->expr()->like('page.roles', $qb->expr()->literal("%$role%")))
                    ->andWhere("page.user is null")
                    ->andWhere("page.parentfor='user'");
                
                $templatesroles=$qb->getQuery()->getResult();
                foreach($templatesroles as $templaterole) {
                    if(!$templatesnotorder->contains($templaterole)) $templatesnotorder->add($templaterole);
                }
            }

            // Récupération des templates par group
            foreach($groups as $group) {
                $qb = $this->createQueryBuilder("page");
                $qb ->where(":group MEMBER OF page.groups")
                    ->andWhere("page.user is null")
                    ->andWhere("page.parentfor='user'")
                    ->setParameter("group",$group->getGroup());
                
                $templatesgroups=$qb->getQuery()->getResult();
                foreach($templatesgroups as $templategroup) {
                    if(!$templatesnotorder->contains($templategroup)) $templatesnotorder->add($templategroup);
                }
            }
            
            // Pour chaque template associé au profil de l'utilisateur on s'assure qu'il possède bien la page
            foreach($templatesnotorder as $template) {
                $exist=$this->getEntityManager()->getRepository("CadolesPortalBundle:Page")->findBy(["page"=>$template]);
                if(!$exist) {
                    $page=$this->clonePage($user,$template);
                }
            }
        }



        // GENERATION DES PAGES UTILISATEURS
        // Une page utilisateur est une page dont il est le propriétaire mais qui n'est pas partagé dans un groupe
        $pagesuser=false;
        if($user) {
            $qb = $this->createQueryBuilder('page');
            $qb ->where("page.user=:user")
                ->setParameter("user",$user)
                ->orderBy('page.roworder', 'ASC')
                ->addOrderBy('page.name', 'ASC');
            $pagesuser=$qb->getQuery()->getResult();
            
            foreach($pagesuser as $key => $pageuser) {
                if(!($pageuser->getGroups()->isEmpty()))
                    unset($pagesuser[$key]);
            }
        }
        
        // Permission sur les pages = il a forcement le droit des les modifier : elles sont à lui
        if($pagesuser) {
            foreach($pagesuser as $pageuser) {
                $pageuser->setCanupdate(true);
            }
        }



        // GENERATION DES PAGES GROUPES DE TRAVAIL
        // Une page groupe de travail est une page associée à un groupe fgcanshare sur lequel l'utilisateur est inscrit
        if($user) {
            // En premier lieu on liste les groupes de travail de l'utilisateur
            $groupsshared=$this ->getEntityManager()->createQueryBuilder()
                                ->select('g')
                                ->from('CadolesCoreBundle:Group','g')
                                ->from('CadolesCoreBundle:UserGroup','ug')
                                ->where('g.fgcanshare=:fgcanshare')
                                ->andWhere('g=ug.group')
                                ->andWhere('ug.user=:user')
                                ->setParameter('fgcanshare',true)
                                ->setParameter('user',$user)
                                ->orderBy('g.label')
                                ->getQuery()->getResult();

            // Pour chaque groupe de travail : on s'assure que le groupe possède au moins une page
            // Sinon création de la page template associée au groupe
            foreach($groupsshared as $key => $groupshared) {
                $pagesshared=$this  ->createQueryBuilder('page')
                                    ->from('CadolesCoreBundle:Group','g')
                                    ->where('g.id=:id')
                                    ->andWhere('g MEMBER OF page.groups')
                                    ->setParameter('id',$groupshared->getId())
                                    ->orderBy('page.roworder')
                                    ->addOrderBy('page.name')
                                    ->getQuery()->getResult();
                
                if(empty($pagesshared)) {
                    unset($groupsshared[$key]);
                }
                else {
                    // Si l'utilisateur est manager du group il aura les permissions de modification sur la page
                    $usergroup=$this->getEntityManager()->getRepository("CadolesCoreBundle:UserGroup")->findOneBy(["user"=>$user,"group"=>$groupshared]);
                    if($usergroup&&$usergroup->getRolegroup()>=90) {
                        foreach($pagesshared as $key2 => $pageshared) {
                            $pagesshared[$key2]->setCanupdate(true);   
                        }
                    }

                    // On calcule le nombre de message non lu pour le groupe
                    $tm = $this ->getEntityManager()->createQueryBuilder()
                                ->select($qb->expr()->count('m.id'))
                                ->from('CadolesWebsocketBundle:Message', 'm')
                                ->where('m.group = :group')
                                ->andWhere('m.user != :user')
                                ->setParameter('group', $groupshared)
                                ->setParameter('user', $user)
                                ->getQuery()->getSingleScalarResult();

                    $tr = $this ->getEntityManager()->createQueryBuilder()
                                ->select($qb->expr()->count('m.id'))
                                ->from('CadolesWebsocketBundle:Message', 'm')
                                ->where('m.group = :group')
                                ->andWhere('m.user != :user')
                                ->andWhere(':user MEMBER OF m.readers')
                                ->setParameter('group', $groupshared)
                                ->setParameter('user', $user)
                                ->getQuery()->getSingleScalarResult();                                
                    foreach($pagesshared as $key2 => $pageshared) {
                        $pagesshared[$key2]->setCounterRead($tm-$tr);   
                    }                    

                    $groupsshared[$key]->pagesshared=$pagesshared;
                }
            }
        }

        $pagesshared=false;
        if($user) {
            $pagesshared=$this->createQueryBuilder('page')
                    ->from('CadolesCoreBundle:Group','g')
                    ->from('CadolesCoreBundle:UserGroup','ug')
                    ->from('CadolesCoreBundle:UserGroup','proprio')
                    ->where('g.fgcanshare=:fgcanshare')
                    ->andWhere('g=ug.group')
                    ->andWhere('ug.user=:user')
                    ->andWhere('g MEMBER OF page.groups')
                    ->andWhere('page.user != :user')
                    ->andWhere('page.user is not null')
                    ->andWhere('proprio.user=page.user')
                    ->andWhere('proprio.group=g')
                    ->setParameter('fgcanshare',true)
                    ->setParameter('user',$user)
                    ->orderBy('page.roworder', 'ASC')
                    ->addOrderBy('page.name', 'ASC')                    
                    ->getQuery()->getResult();
        }
        
        // GENERATION DES PAGES ADMINISTRATEUR
        // Initialisation du calcul des pages
        $pagesnotorder=new ArrayCollection();

        // Récupération des pages par rôles
        foreach($roles as $role) {
            $qb = $this->createQueryBuilder("page");
            $qb ->where($qb->expr()->like('page.roles', $qb->expr()->literal("%$role%")))
                ->andWhere("page.user is null")
                ->andWhere("page.parentfor is null");
            
            $pagesroles=$qb->getQuery()->getResult();
            foreach($pagesroles as $pagerole) {
                if(!$pagesnotorder->contains($pagerole)) $pagesnotorder->add($pagerole);
            }
        }

        // Récupération des pages par group
        foreach($groups as $group) {
            if(!$group->getGroup()->getFgcanshare()) {
                $qb = $this->createQueryBuilder("page");
                $qb ->where(":group MEMBER OF page.groups")
                    ->andWhere("page.user is null")
                    ->andWhere("page.parentfor is null")
                    ->setParameter("group",$group->getGroup());
                
                $pagesgroups=$qb->getQuery()->getResult();
                foreach($pagesgroups as $pagegroup) {
                    if(!$pagesnotorder->contains($pagegroup)) $pagesnotorder->add($pagegroup);
                }
            }
        }

        // Permission sur les pages
        foreach($pagesnotorder as $pageadmin) {
            $pageadmin->setCanupdate(false);
        }

        // Trie des pages
        $pages = $pagesnotorder->getIterator();
        $pages->uasort(function ($first, $second) {
            return (int) $first->getRowOrder() > (int) $second->getRowOrder() ? 1 : -1;
        });

        // Afficher par défaut la pagebookmarké par l'utilisateur en préférence
        if($user&&!isset($id)) {
            $preference=$user->getPreference();
            if(is_array($preference)&&array_key_exists("pagebookmark",$preference)) {
                $id=$preference["pagebookmark"][0];
            }
        }

        // On récupère la page à afficher
        $entity=false;
        if(isset($id)) {
            $entity = $this->find($id);

            // On s'assure que la page fait partie des pages du profil
            $have=false;
            foreach($pages as $v) {
                if($v == $entity)
                    $have=true;
            }
            if($pagesuser) {
                foreach($pagesuser as $v) {
                    if($v == $entity)
                        $have=true;
                }
            }
            if($groupsshared) {
                foreach($groupsshared as $groupshared) {
                    foreach($groupshared->pagesshared as $v) {
                        if($v == $entity)
                            $have=true;
                    }
                }
            }

            if(!$have) $entity=false;
        }

        // ou On récupère la premier page profilée comme page d'accueil
        if(!$entity) {
           $pages->rewind();
            if($pages->current()) {
                $id=$pages->current()->getId();
                $entity = $this->find($id);
            }

            // Si aucune page profilé on récupère la premiere page perso
            if(!$entity) {
                if($pagesuser)
                    $entity=$pagesuser[0];
            }

            // Si aucune page profilé on récupère la premiere page perso
            if(!$entity) {
                if($groupsshared) {
                    if($groupsshared[0])
                        $entity=$groupsshared[0]->pagesshared[0];
                }
            }            
        }

        // ou On récupère la premiere page de l'utilisateur
        if(!$entity && !empty($pagesuser)) {
            $entity=$pagesuser[$this->firstkey($pagesuser)];
        }

        // ou On récupère la premiere page partagées
        if(!$entity && !empty($pagesshared)) {
            $entity=$pagesshared[$this->firstkey($pagesshared)];
        }        
    }

    public function getPermission($user,$page,&$cansee,&$canupdate,&$canadd) {
        // si page de l'utilisateur
        if($page->getUser()==$user&&!is_null($user)) {
            $cansee=true;
            $canupdate=true;
            $canadd=true;
        }
        else {
            $canupdate=false;
            $cansee=false;

            // Profilage
            $roles=($user?$user->getRoles():["ROLE_ANONYME"]);
            $groups=($user?$user->getGroups():[]);

            // La page est-elle dans les pages associées à un partage de group ?
            /*
            $inpagesshared=$this->createQueryBuilder('page')
                    ->from('CadolesCoreBundle:Group','g')
                    ->from('CadolesCoreBundle:UserGroup','ug')
                    ->from('CadolesCoreBundle:UserGroup','proprio')
                    ->where('g.fgcanshare=:fgcanshare')
                    ->andWhere('page.id = :id')
                    ->andWhere('g=ug.group')
                    ->andWhere('ug.user=:user')
                    ->andWhere('g MEMBER OF page.groups')
                    ->andWhere('page.user != :user')
                    ->andWhere('page.user is not null')
                    ->andWhere('proprio.user=page.user')
                    ->andWhere('proprio.group=g')
                    ->setParameter("id",$page->getId())
                    ->setParameter('fgcanshare',true)
                    ->setParameter('user',$user)
                    ->getQuery()->getResult();
            if($inpagesshared) $cansee=true;
            */

            // La page est-elle dans les pages associées au role de l'utilisateur ?
            foreach($roles as $role) {
                $qb = $this->createQueryBuilder("page");
                $qb ->where($qb->expr()->like('page.roles', $qb->expr()->literal("%$role%")))
                    ->andWhere("page.id=:id")
                    ->andWhere("page.user is null")
                    ->setParameter("id",$page->getId());
                $inpagerole=$qb->getQuery()->getResult();
                if($inpagerole) $cansee=true;
            }   
            

            // La page est-elle dans les pages associées aux groupes de l'utilisateur ?
            foreach($groups as $group) {
                $qb = $this->createQueryBuilder("page");
                $qb ->where(":group MEMBER OF page.groups")
                    ->andWhere("page.id=:id")
                    ->andWhere("page.id=:id")
                    ->setParameter("id",$page->getId())
                    ->setParameter("group",$group->getGroup());
                
                $inpagegroup=$qb->getQuery()->getResult();

                if($inpagegroup) {
                    $cansee=true;
                    // Est-il manager du groupe
                    if($group->getGroup()->getFgcanshare()) {
                        if($group->getRolegroup()>=90) $canupdate=true;
                        if($group->getRolegroup()>=50) $canadd=true;
                    }
                }
            }            
        }
    }

    public function clonePage($user,$template) {
        $page=new Page();
        $page->setName($template->getName());
        $page->setRoworder($template->getRoworder());
        $page->setMaxwidth($template->getMaxwidth());
        $page->setUrl($template->getUrl());
        $page->setHtml($template->getHtml());
        $page->setTemplate($template->getTemplate());
        $page->setPagecategory($template->getPagecategory());
        $page->setUser($user);
        $page->setPage($template);

        $this->getEntityManager()->persist($page);
        $this->getEntityManager()->flush();  

        $widgets=$template->getPagewidgets();
        foreach($widgets as $widget) {
            $pagewidget=new Pagewidget();
            $pagewidget->setName($widget->getName());
            $pagewidget->setLoc($widget->getLoc());
            $pagewidget->setRoworder($widget->getRoworder());
            $pagewidget->setHeight($widget->getHeight());
            $pagewidget->setAutoajust($widget->getAutoajust());
            $pagewidget->setBorder($widget->getBorder());
            $pagewidget->setOpened($widget->getOpened());
            $pagewidget->setColorheaderback($widget->getColorheaderback());
            $pagewidget->setColorheaderfont($widget->getColorheaderfont());
            $pagewidget->setColorbodyback($widget->getColorbodyback());
            $pagewidget->setColorbodyfont($widget->getColorbodyfont());
            $pagewidget->setParameter($widget->getParameter());
            $pagewidget->setPage($page);
            $pagewidget->setWidget($widget->getWidget());
            $pagewidget->setIcon($widget->getIcon());

            $this->getEntityManager()->persist($pagewidget);
            $this->getEntityManager()->flush();                         
            
            // dupliquer slide et bookmarks ??
        }    

        return $page;
    }

    private function firstkey($array) {
        foreach($array as $key => $unused) {
            return $key;
        }
        return NULL;
    }
}
