<?php

namespace ModulesGarden\Servers\OpenXchange\App\UI\Client\EmailAccount\Providers;

use ModulesGarden\Servers\OpenXchange\App\Libs\RestApi;
use ModulesGarden\Servers\OpenXchange\App\Helpers\Helper;
use ModulesGarden\Servers\OpenXchange\App\UI\Client\EmailAccount\Constants;
use ModulesGarden\Servers\OpenXchange\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
use ModulesGarden\Servers\OpenXchange\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
use ModulesGarden\OpenXchangeAddon\Core\Models\ModuleSettings\Model;
use ModulesGarden\Servers\OpenXchange\App\Models\ProductConfiguration;

/**
 *
 * Created by PhpStorm.
 * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
 * Date: 18.09.19
 * Time: 09:35
 * Class EditAccountDataProvider
 */
class EditAccountDataProvider extends BaseDataProvider
{
    public function read()
    {
        $params         = Helper::moduleParams($this->request->getValue('id'));
        $context        = new RestApi($params);
        $userIdPunycode = Helper::convertEmailToPunnycode($this->actionElementId);
        $user           = $context->getUserData($userIdPunycode);

        $this->availableValues['emailType']      = $this->getAvailableEmailTypes($params);
        $this->availableValues['emailAddonType'] = $this->getAvailableAddons($params);

        //get avaliable lang
        $langDataRaw = Model::where('setting', '=', 'language')->get()->toArray();
        $langData    = unserialize($langDataRaw[0]['value']);

        if (is_array($langData) && !empty($langData))
        {
            foreach (Constants::LANGUAGES as $name => $language)
            {
                if (in_array($language, $langData))
                {
                    $this->availableValues['language'][$language] = $name;
                }
            }
        }
        else
        {
            foreach(Constants::LANGUAGES as $name => $language)
            {
                $this->availableValues['language'][$language] = $name;
            }
        }

        $this->optGroups['timezone'] = Constants::TIMEZONES;
        
        $permissionsData = $context->getUserPermissions($user->name);
        
        if ($permissionsData->send && $permissionsData->receive && $permissionsData->maillogin && $permissionsData->weblogin)
        {
            $mailenabled = 'on';
        }
        else
        {
            $mailenabled = 'off';
        }

        $currentQuotaLimit = property_exists($user, 'unifiedQuota') ? $user->unifiedQuota : $user->mailQuota;

        $this->data = [
            'id' => $user->name,
            //'primaryEmail' => $user->mail,
            'primaryEmail'   => explode('@', $user->mail)[0],
            'display_name'   => $user->displayName,
            'mailenabled'    => $mailenabled,
            'firstname'      => $user->givenName,
            'lastname'       => $user->surName,
            'language'       => $user->language,
            'timezone'       => $user->timezone,
            //'mailenabled'  => $user->webLoginEnabled == true ? "on" : "",
            'quota'          => $currentQuotaLimit == '-1' ? 'Unlimited' : $currentQuotaLimit,
            'emailType'      => $this->getEmailType($user),
            'emailAddonType' => $this->getSelectedAddons($user)
        ];

        $this->data['domain'] = $params['domain'];
        
        //check if autofill option is "on" autofillGen
        $autofillOptRaw = Model::where('setting', '=', 'autofill')->get()->toArray();
        
        $this->data['autofillGen'] = $autofillOptRaw[0]['value'];
    }

    public function update()
    {
        try
        {
            $params            = Helper::moduleParams($this->request->getValue('id'));
            $context           = new RestApi($params);
            $user              = $context->getUserData($this->formData['id']);
            $limit             = Helper::accountsLimit($params);
            $limit2            = Helper::quotaLimit($params);
            $freeAcc           = Helper::freeAccountsLimit($params);
            $maxQuota          = Helper::maxQuotaLimit($params);
            $accountsAndQuota  = $this->countUsersAndQuota($params, $user);
            $currentQuotaLimit = property_exists($user, 'unifiedQuota') ? $user->unifiedQuota : $user->mailQuota;
            $summaryQuota      = $accountsAndQuota['quotaForAccounts'] - $currentQuotaLimit + $this->formData['quota'];

            if($this->formData['quota'] <= 0)
            {
                return (new HtmlDataJsonResponse())->setMessageAndTranslate('quotaLimitWrong')->setStatusError();
            }

            if($limit2 > 0 && $this->formData['quota'] > $limit2)
            {
                return (new HtmlDataJsonResponse())->setMessageAndTranslate('quotaLimit')->setStatusError();
            }

            if($summaryQuota > $maxQuota)
            {
                return (new HtmlDataJsonResponse())->setMessageAndTranslate('quotaLimitExtended')->setStatusError();
            }

            try
            {
                if ($limit == 'unlimited')
                {
                    $accLimit = 'unlimited';
                }
                else
                {
                    $accLimit         = $limit + $freeAcc;
                }
                //$accLimit         = $limit + $freeAcc;
                $accProdLimit     = Helper::accountsProdLimit($params);
                $accSecLimit      = Helper::accountsSecLimit($params);
                $accProdSecLimit  = Helper::accountsProdSecLimit($params);
                $accGuardLimit    = Helper::accountsGuardLimit($params);
                $accAiLimit       = Helper::accountsAiLimit($params);
                $selectedType     = $this->formData['emailType'];
                $emailTypeChenged = Helper::checkIfAccountTypeChanged($user, $selectedType);

                if ($emailTypeChenged)
                {
                    switch ($selectedType)
                    {
                        case 'cloud_pim':
                            if ($accLimit != 'unlimited' && $accountsAndQuota['accountsCount']['emailAccs'] >= $accLimit)
                            {
                                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsLimitEss')->setStatusError();
                            }

                            break;
                        case 'cloud_single_web':
                            if ($accLimit != 'unlimited' && $accountsAndQuota['accountsCount']['emailAccs'] >= $accLimit)
                            {
                                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsLimitBasic')->setStatusError();
                            }

                            break;
                        case 'cloud_productivity_guard':
                            if ($accLimit != 'unlimited' && $accountsAndQuota['accountsCount']['emailAccs'] >= $accLimit)
                            {
                                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsLimitPremium')->setStatusError();
                            }

                            break;
                        case 'cloud_productivity':
                            if($accProdLimit != 'unlimited' && $accountsAndQuota['accountsCount']['emailProdAccs'] >= $accProdLimit)
                            {
                                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsLimitProd')->setStatusError();
                            }

                            break;
                        case 'cloud_security':
                            if($accSecLimit != 'unlimited' && $accountsAndQuota['accountsCount']['emailSecAccs'] >= $accSecLimit)
                            {
                                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsLimitSec')->setStatusError();
                            }

                            break;
                        case 'cloud_productivity_security':
                            if($accProdSecLimit != 'unlimited' && $accountsAndQuota['accountsCount']['emailProdSecAccs'] >= $accProdSecLimit)
                            {
                                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsLimitProdSec')->setStatusError();
                            }

                            break;
                        default:
                            break;
                    }
                }
                
                $selectedAddons = $this->formData['emailAddonType'];
                
                if ($selectedAddons && !empty($selectedAddons))
                {
                    foreach ($selectedAddons as $selectedAddon)
                    {
                        if ($selectedAddon == 'guard')
                        {
                            if($accGuardLimit != 'unlimited' && $accountsAndQuota['accountsCount']['emailGuardAccs'] >= $accGuardLimit)
                            {
                                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsLimitGuard')->setStatusError();
                            }
                        }
                        elseif($selectedAddon == 'ai')
                        {
                            if($accAiLimit != 'unlimited' && $accountsAndQuota['accountsCount']['emailAiAccs'] >= $accAiLimit)
                            {
                                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsLimitAi')->setStatusError();
                            }
                        }
                    }
                }

                $domainPunnycode = \WHMCS\Domains\Idna::toPunycode($this->formData['domain']);

                $parameters = [
                    //'display_name' => $this->formData['display_name'],
                    'display_name'  => $this->formData['firstname'].' '.$this->formData['lastname'],
                    'given_name'    => $this->formData['firstname'],
                    'sur_name'      => $this->formData['lastname'],
                    'language'      => $this->formData['language'],
                    'timezone'      => $this->formData['timezone'],
                    'quota'         => $this->formData['quota'],
                    'name'          => $this->formData['primaryEmail'].'@'.$domainPunnycode,
                    'primaryEmail'  => $this->formData['primaryEmail'].'@'.$domainPunnycode,
                    'password'      => $this->formData['password'],
                    'resetPassword' => $this->formData['resetPassword']
                ];

                if ($selectedType == 'cloud_productivity_guard')
                {
                    $parameters['emailType'] = ['cloud_productivity', 'guard'];
                }
                else
                {
                    $parameters['emailType'] = [$this->formData['emailType']];
                }
                
                if (!empty($selectedAddons))
                {
                    if (in_array('guard', $selectedAddons))
                    {
                        if (!in_array('guard', $parameters['emailType']))
                        {
                            array_push($parameters['emailType'], 'guard');
                        }
                    }
                    if(in_array('ai', $selectedAddons))
                    {
                        array_push($parameters['emailType'], 'ai');
                    }
                }

                $result  = $context->updateUser($user->name, $parameters);
                
                if ($this->formData['mailenabled'] == 'off')
                {
                    $context->suspendUser($user->name);
                }
                elseif ($this->formData['mailenabled'] == 'on')
                {
                    $context->unsuspendUser($user->name);
                }
            }
            catch(\Exception $e)
            {
                // Do nothing
            }

            if($result == '')
            {
                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountHasBeenUpdated')->setStatusSuccess();
            }
            else
            {
                return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsUpdateError')->setStatusError();
            }
        }
        catch(\Exception $e)
        {
            return (new HtmlDataJsonResponse())->setMessageAndTranslate('emailAccountsUpdateError')->setStatusError();
        }
    }

    private function countUsersAndQuota($params, $currentUser)
    {
        $context         = new RestApi($params);
        $usersList       = $context->listAllUsers();
        $config          = ProductConfiguration::config($params['packageid']);
        $selectedProduct = $config['selected_product'];

        $quotaForAccounts = 0;

        foreach($usersList as $key => $user)
        {
            if($user->isContextAdmin == true)
            {
                unset($usersList[$key]);
                continue;
            }

            $quotaForAccounts += property_exists($user, 'unifiedQuota') ? $user->unifiedQuota : $user->mailQuota;

            if($user->name === $currentUser->name)
            {
                unset($usersList[$key]);
            }
        }

        $freeAcc = Helper::freeAccountsLimit($params);

        /*if ($freeAcc > 0)
        {*/
            $emailAccs        = 0;
            $emailProdAccs    = 0;
            $emailSecAccs     = 0;
            $emailProdSecAccs = 0;
            $emailProdGuard   = 0;
            $emailProdAi      = 0;

            foreach ($usersList as $account)
            {
                $accAttributes = $account->classOfService;

                if ((in_array('cloud_pim', $accAttributes) || in_array('cloud_single_web', $accAttributes)) && count($accAttributes) == 1)
                {
                    $emailAccs++;
                }
                elseif ((in_array('cloud_productivity', $accAttributes) && in_array('guard', $accAttributes)) && count($accAttributes) == 2)
                {
                    if ($selectedProduct == 'cloud_productivity_guard' && $config['product_accounts'] && $config['product_accounts'] > 0)
                    {
                        $emailAccs++;
                    }
                    else
                    {
                        $emailProdAccs++;
                        $emailProdGuard++;
                    }
                }
                elseif ((in_array('cloud_productivity', $accAttributes) && in_array('guard', $accAttributes)) && in_array('ai', $accAttributes))
                {
                    if ($selectedProduct == 'cloud_productivity_guard' && $config['product_accounts'] && $config['product_accounts'] > 0)
                    {
                        $emailAccs++;
                        $emailProdAi++;
                    }
                    else
                    {
                        $emailProdAccs++;
                        $emailProdGuard++;
                        $emailProdAi++;
                    }
                }
                else
                {
                    if (in_array('cloud_pim', $accAttributes))
                    {
                        $emailAccs++;
                    }
                    if (in_array('cloud_single_web', $accAttributes))
                    {
                        $emailAccs++;
                    }
                    if (in_array('cloud_productivity', $accAttributes))
                    {
                        $emailProdAccs++;
                    }
                    if(in_array('cloud_security', $accAttributes))
                    {
                        $emailSecAccs++;
                    }
                    if (in_array('cloud_productivity_security', $accAttributes))
                    {
                        $emailProdSecAccs++;
                    }
                    if (in_array('guard', $accAttributes))
                    {
                        $emailProdGuard++;
                    }
                    if (in_array('ai', $accAttributes))
                    {
                        $emailProdAi++;
                    }
                }
            }

            return ['accountsCount' => [
                'emailAccs'        => $emailAccs,
                'emailProdAccs'    => $emailProdAccs,
                'emailProdSecAccs' => $emailProdSecAccs,
                'emailSecAccs'     => $emailSecAccs,
                'emailGuardAccs'   => $emailProdGuard,
                'emailAiAccs'      => $emailProdAi],
                'quotaForAccounts' => $quotaForAccounts
            ];
        /*}
        else
        {
            return ['accountsCount' => count($usersList), 'quotaForAccounts' => $quotaForAccounts];
        }*/
    }

    public function getAvailableAddons($params)
    {
        $configOptions     = $params['configoptions'];
        $allowedAddonsData = [];
        
        if ($configOptions && !empty($configOptions))
        {
            if (isset($configOptions['acc_limit_guard']) && $configOptions['acc_limit_guard'] > 0)
            {
                $allowedAddonsData['guard'] = array_search('guard', Constants::getTranslatedAddonsReal());
            }
            
            if (isset($configOptions['acc_limit_ai']) && $configOptions['acc_limit_ai'] > 0)
            {
                $allowedAddonsData['ai'] = array_search('ai', Constants::getTranslatedAddonsReal());
            }
        }

        if (empty($allowedAddonsData))
        {
            $config = ProductConfiguration::config($params['packageid']);

            if ($config['email_accounts_guard'] && $config['email_accounts_guard'] != 0)
            {
                $allowedAddonsData['guard'] = array_search('guard', Constants::getTranslatedAddonsReal());
            }

            if ($config['email_accounts_ai'] && $config['email_accounts_ai'] != 0)
            {
                $allowedAddonsData['ai'] = array_search('ai', Constants::getTranslatedAddonsReal());
            }
        }

        return $allowedAddonsData;
    }

    public function getAvailableEmailTypes($params) 
    {
        $configOptions    = $params['configoptions'];
        $allowedTypesData = [];
            
        if ($configOptions && !empty($configOptions))
        {
            if (isset($configOptions['acc_limit']) && $configOptions['acc_limit'] > 0)
            {
                $config                                        = ProductConfiguration::config($params['packageid']);
                $allowedTypesData[$config['selected_product']] = array_search($config['selected_product'], Constants::getTranslatedPackages());
            }

            if (isset($configOptions['acc_limit_productivity']) && $configOptions['acc_limit_productivity'] > 0)
            {
                $allowedTypesData['cloud_productivity'] = array_search('cloud_productivity', Constants::getTranslatedAddons());
            }

            if (isset($configOptions['acc_limit_secure']) && $configOptions['acc_limit_secure'] > 0)
            {
                $allowedTypesData['cloud_security'] = array_search('cloud_security', Constants::getTranslatedAddons());
            }

            if (isset($configOptions['acc_limit_productivity_secure']) && $configOptions['acc_limit_productivity_secure'] > 0)
            {
                $allowedTypesData['cloud_productivity_security'] = array_search('cloud_productivity_security', Constants::getTranslatedAddons());
            }
        }

        //if (empty($allowedTypesData))
        //{
            $config = ProductConfiguration::config($params['packageid']);

            if ($config['product_accounts'] && $config['product_accounts'] != 0)
            {
                if (isset($configOptions['acc_limit']) && $configOptions['acc_limit'] == 0)
                {
                    //do nothing
                }
                else
                {
                    $allowedTypesData[$config['selected_product']] = array_search($config['selected_product'], Constants::getTranslatedPackages());
                }
            }
 
            if ($config['email_accounts_productivity'] && $config['email_accounts_productivity'] != 0)
            {
                if (isset($configOptions['acc_limit_productivity']) && $configOptions['acc_limit_productivity'] == 0)
                {
                    //do nothing
                }
                else
                {
                    $allowedTypesData['cloud_productivity'] = array_search('cloud_productivity', Constants::getTranslatedAddons());
                }
            }

            if ($config['email_accounts_security'] && $config['email_accounts_security'] != 0)
            {
                if (isset($configOptions['acc_limit_secure']) && $configOptions['acc_limit_secure'] == 0)
                {
                    //do nothing
                }
                else
                {
                    $allowedTypesData['cloud_security'] = array_search('cloud_security', Constants::getTranslatedAddons());
                }
            }

            if ($config['email_accounts_productivity_security'] && $config['email_accounts_productivity_security'] != 0)
            {
                if (isset($configOptions['acc_limit_productivity_secure']) && $configOptions['acc_limit_productivity_secure'] == 0)
                {
                    //do nothing
                }
                else
                {
                    $allowedTypesData['cloud_productivity_security'] = array_search('cloud_productivity_security', Constants::getTranslatedAddons());
                }
            }
        //}

        return $allowedTypesData;
    }

    private function getEmailType($data)
    {
        $type          = '';
        $accAttributes = $data->classOfService;

        if (in_array('cloud_productivity', $accAttributes) && in_array('guard', $accAttributes) && count($accAttributes) == 2)
        {
            $type = 'cloud_productivity_guard';
        }
        else
        {
            foreach ($accAttributes as $attribute)
            {
                if (!in_array($attribute, Constants::getTranslatedAddonsReal()))
                {
                    $type = $attribute;
                }
            }
        }

        if (!$type || $type == '')
        {
            $type = '---';
        }

        return $type;
    }
    
    private function getSelectedAddons($data)
    {
        $addons        = [];
        $accAttributes = $data->classOfService;

        if (in_array('cloud_productivity', $accAttributes) && in_array('guard', $accAttributes) && count($accAttributes) == 2)
        {
            $addons = [];
        }
        else
        {
            if (in_array('guard', $accAttributes))
            {
                array_push($addons, 'guard');
            }

            if (in_array('ai', $accAttributes))
            {
                array_push($addons, 'ai');
            }
        }

        return $addons;
    }
}
