<?php
/**
 * Copyright (c) 2016 Serhii Borodai <clarifying@gmail.com>.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 *
 */

namespace App\Model;


use App\Entity\User;
use App\Model\IdentityTrait\Identity;
use Ramsey\Uuid\Uuid;

use \Zend\Db\TableGateway\TableGateway;
use \Zend\Hydrator\DelegatingHydrator;
use \Monolog\Logger;

/**
 * Class Users
 * @package App\Model
 */
class Users extends Common implements ModelIdentity
{

    use Identity;

    const RANDOM_PASSWORD_LENGTH = 16;
    const KEYSPACE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*_';    
    
    /**
     *
     * @var UsersCategory
     */
    protected $userCategiriesModel;    
    
    /**
     *
     * @var Countries
     */
    protected $countryModel;
    
    /**
     *
     * @var Currencies
     */
    protected $currencyModel;
    
    /**
     *
     * @var Supports
     */
    protected $supportModel;
    

    public function __construct(TableGateway $tableGateway, DelegatingHydrator $delegatingHydrator, Logger $logger, UsersCategory $categories, Countries $countries, Currencies $currencies, Supports $supports)
    {
        parent::__construct($tableGateway, $delegatingHydrator, $logger);
        
        $this->userCategiriesModel = $categories;
        $this->countryModel = $countries;
        $this->currencyModel = $currencies;
        $this->supportModel = $supports;
    }
    
    /**
     * @param null $where
     * @return User
     */
    public function findOne($where = null)
    {
        /** @var User $result */
        $result = $this->findBy($where);
        return $result ? current($result) : null;
    }
    
    public function findById($id)
    {
        return $this->findOne(['id' => $id]);
    }

    public function findBy($where = null, $limit = null, $order = null) 
    {
        if($where['category']) {
            $where['id'] = $this->userCategiriesModel->getUsersId($where['category']);
            unset($where['category']);
        }
        
        $result = parent::findBy($where, $limit, $order);
        if($result) {
            $tmp = array();            
                        
            foreach($result as $user) {
                $categories = $this->userCategiriesModel->findBy([
                   'user_id'  => $user->getId()
                ]);
                if($categories) {
                    $user->setCategories($categories);
                }
                
                $country = $this->countryModel->findOne([
                    'code' => $user->getCountryCode()
                ]);
                if($country) {
                    $user->setCountry($country);
                }
                
                $manager = $this->supportModel->findById($user->getSupportId());
                if($manager) {
                    $user->setManager($manager);
                }
                
                $tmp[$user->getId()] = $user;
            }
            
            $result = $tmp;
        }
        return $result;
    }
    
    public function getCountryCodes()
    {      
        $adapter = $this->tableGateway->getAdapter();
        
        $sql = 'SELECT country_code, count(1) as n'
                . ' FROM ' . (string) $this->tableGateway->getTable() 
                . ' WHERE country_code != ""'
                . ' GROUP BY country_code'
                . ' ORDER BY n desc';
        $res = $adapter->query($sql, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
        
        $countryCodes = array();
        if($res) {
            foreach($res as $r) {
                $countryCodes[] = $r['country_code'];                
            }
        }

        return $countryCodes;
    }

    /**
     * @param User $entity
     * @return int
     *
     * @throws \Exception
     */
    public function save($entity)
    {
        if (!$entity instanceof User) {
            throw new \Exception('Instance of "User" required');
        }
        
        if (!$entity->getUuid()) {
            $entity->setUuid(Uuid::uuid5(Uuid::NAMESPACE_OID, $entity->getEmail())->toString());
        }
        
        $id = parent::save($entity);
        $categories = array();
        
        $entity_categories = $entity->getCategories();
        if($entity_categories) {
            foreach($entity_categories as $category) {
                $cat = new \App\Entity\UserCategory();
                $cat->setUserId($id);
                $cat->setCategoryId($category->getId());
                
                $categories[] = $cat;
            }
        }
        
        $this->userCategiriesModel->saveAll($id, $categories);
        return $id;
    }

    /**
     *
     * @return string
     */
    public function generateRandomPassword()
    {
        $pass = '';
        $max = mb_strlen(self::KEYSPACE) - 1;
        for ($i = 0; $i < self::RANDOM_PASSWORD_LENGTH; ++$i) {
            $pass .= self::KEYSPACE[random_int(0, $max)];
        }
        return $pass;
    }
    
    
    public function findBySupportId($id)
    {
        
        $listUsers = $this->findBy($where=[
            'support_id' => $id
        ], $limit=null, $order=null);
        
        $listUsersId = array();
        foreach($listUsers as $itemUser) {
            $listUsersId[] = $itemUser->getId();
        }
        
        return $listUsersId;
    }

    
}