<?php

namespace ThurData\Servers\KerioEmail\App\Libs\Kerio\Components\Api\Soap\Services\Update;


use ThurData\Servers\KerioEmail\App\Enums\ProductParams;
use ThurData\Servers\KerioEmail\App\Enums\Kerio;
use ThurData\Servers\KerioEmail\App\Libs\Kerio\Components\Api\Soap\Interfaces\ApiService;
use ThurData\Servers\KerioEmail\App\Libs\Kerio\Components\Api\Soap\Models\DistributionList;
use ThurData\Servers\KerioEmail\App\Libs\Kerio\Components\Api\Soap\Models\Domain;
use ThurData\Servers\KerioEmail\App\Libs\Kerio\Components\Api\Soap\Services\Create\CreateDistributionList;

/**
 *
 * Created by PhpStorm.
 * User: ThurData
 * Date: 02.10.19
 * Time: 09:42
 * Class UpdateDistributionList
 */
class UpdateDistributionList extends CreateDistributionList
{
    public function isValid()
    {
        /**
         *
         * check that the owners are valid
         */
        foreach($this->formData['owners'] as $owner)
        {
            $result = $this->api->account->getAccountId($owner);
            if($result->getLastError())
            {
                $this->setError($this->api->account->getLastResult()->getLastErrorCode());
                return false;
            }
        }

        /**
         *
         * check that the domains from aliases are valid
         */
        foreach($this->formData['emailAliases'] as $alias)
        {
            $aliasParts = explode('@', $alias);
            $domain = new Domain();
            $domain->setName($aliasParts[1]);
            $result = $this->api->domain->getDomain($domain);
            if($result->getLastError())
            {
                $this->setError($this->api->domain->getLastResult()->getLastErrorCode());
                return false;
            }
        }

        if(!$this->api)
        {
            $this->setError('API Not Found');
            return false;
        }

        return true;
    }

    /**
     * update aliases service
     *
     * @return bool|mixed
     */
    public function process()
    {

        $list = $this->getModel();
        /**
         * create list
         */
        $result = $this->api->distributionList->update($list);

        if (!$result)
        {
            $this->setError($this->api->distributionList->getLastResult()->getLastErrorCode());
            return false;
        }

        /**
         *
         * update members list
         */
        $this->updateMembers($list, $this->formData['memberListActually'], $this->formData['memberList']);

        /**
         *
         * update owners list
         */
        $this->updateOwners($list, $this->formData['ownersActually'], $this->formData['owners']);


        /**
         *
         * update aliases
         */
        $this->updateListAliases($list, $this->formData['emailAliasesActually'], $this->formData['emailAliases']);


        return true;
    }

    /**
     * @return DistributionList
     */
    protected function getModel()
    {
        $list = new DistributionList();
        $list->setId($this->formData['id']);
        $list->setAttr(DistributionList::ATTR_DISPLAY_NAME, $this->formData['displayName']);
        $list->setAttr(DistributionList::ATTR_DESCRIPTION, $this->formData['description']);
        $list->setAttr(DistributionList::ATTR_SUBSCRIPTION_REQUEST, $this->formData['subscriptionRequest']);
        $list->setAttr(DistributionList::ATTR_UNSUBSCRIPTION_REQUEST, $this->formData['unsubscriptionRequest']);
        $list->setAttr(DistributionList::REPLY_TO_DISPLAY, $this->formData['replyDisplayName']);
        $list->setAttr(DistributionList::REPLY_TO_ADDRESS, $this->formData['replyEmailAddress']);

        $notify = $this->formData['sharesNotify'] === ProductParams::SWITCHER_ENABLED ? Kerio::ATTR_ENABLED : Kerio::ATTR_DISABLED;
        $list->setAttr(DistributionList::ATTR_NOTIFY_SHARES, $notify);

        $hideGal = $this->formData['hideGal'] === ProductParams::SWITCHER_ENABLED ? Kerio::ATTR_ENABLED : Kerio::ATTR_DISABLED;
        $list->setAttr(DistributionList::ATTR_HIDE_IN_GAL, $hideGal);

        $status = $this->formData['receiveMail'] === ProductParams::SWITCHER_ENABLED ? Kerio::ENABLED : Kerio::DISABLED;
        $list->setAttr(DistributionList::ATTR_MAIL_STATUS, $status);

        $replyEnabled = $this->formData['replyEmail'] === ProductParams::SWITCHER_ENABLED ? Kerio::ATTR_ENABLED : Kerio::ATTR_DISABLED;
        $list->setAttr(DistributionList::REPLY_TO_ENABLED, $replyEnabled);


        if ($this->formData['dynamicGroup'] === ProductParams::SWITCHER_ENABLED)
        {
            $list->setDynamic(true);
        }

        return $list;
    }

    /**
     * @param DistributionList $list
     * @param array $currentMembers
     * @param array $newMembers
     * @return bool
     */
    protected function updateMembers(DistributionList $list, $currentMembers = [], $newMembers = [])
    {
        /**
         *
         * get members which should be added
         */
        $add = array_diff((array) $newMembers,(array) $currentMembers);

        /**
         *
         * add members to list
         */
        $this->addListMembers($list, $add);

        /**
         *
         * get members which should be removed
         */
        $remove = array_diff((array)$currentMembers,(array) $newMembers);

        /**
         *
         * remove members
         */
        $this->removeMembers($list, $remove);

        /**
         *
         * return success
         */
        return true;
    }

    /**
     * @param DistributionList $list
     * @param array $members
     * @return bool
     */
    protected function removeMembers(DistributionList $list, $members = [])
    {
        /**
         *
         * set member list as empty
         */
        $list->setMembers([]);

        /**
         *
         * add members to remove
         */
        foreach ($members as $owner)
        {
            $list->addMember($owner);
        }

        /**
         *
         * remove old members
         */
        $result = $this->api->distributionList->deleteMembers($list);
        if (!$result)
        {
            $this->setError($this->api->distributionList->getLastResult()->getLastErrorCode());
            return false;
        }

        /**
         * return success
         */
        return true;
    }

    /**
     *
     * update owners list
     *
     * @param DistributionList $list
     * @param array $currentOwners
     * @param array $newOwners
     * @return bool
     */
    protected function updateOwners(DistributionList $list, $currentOwners = [], $newOwners = [])
    {
        /**
         *
         * get owners which should be added
         */
        $add = array_diff((array) $newOwners, (array) $currentOwners);
        /**
         *
         * add new owners
         */
        $this->addListOwners($list, $add);
        /**
         *
         * get members which should be removed
         */
        $remove = array_diff((array) $currentOwners,(array) $newOwners);

        /**
         *
         * remove other owners
         */
        $this->removeOwners($list, $remove);

        /**
         *
         */
        return true;

    }

    /**
     *
     * remove old owners
     *
     * @param DistributionList $list
     * @param array $owners
     * @return bool
     */
    protected function removeOwners(DistributionList $list, $owners = [])
    {
        /**
         * set owner list as empty
         */
        $list->setOwners([]);

        /**
         * add owners which should be deleted
         */
        foreach ($owners as $owner)
        {
            $list->addOwner($owner);
        }

        /**
         * delete owners from list
         */
        $result = $this->api->distributionList->deleteOwners($list);
        if (!$result)
        {
            $this->setError($this->api->distributionList->getLastResult()->getLastErrorCode());
            return false;
        }

        return true;
    }

    /**
     * update aliases list
     *
     * @param DistributionList $list
     * @param array $currentAliases
     * @param array $newAliases
     * @return bool
     */
    protected function updateListAliases(DistributionList $list, $currentAliases = [], $newAliases = [])
    {
        /**
         *
         * get aliases to add
         */
        $add = array_diff((array) $newAliases,(array) $currentAliases);

        /**
         *
         * add aliases
         */
        $this->addListAliases($list, $add);

        /**
         *
         * get aliases to remove
         */
        $remove = array_diff((array) $currentAliases,(array) $newAliases);

        /**
         *
         * remove aliases
         */
        $this->removeAliases($list, $remove);


        return true;
    }

    /**
     * remove aliases
     *
     * @param DistributionList $list
     * @param array $aliases
     * @return bool
     */
    public function removeAliases(DistributionList $list, $aliases = [])
    {
        /**
         * remove each alias
         */
        foreach ($aliases as $alias)
        {
            $list->setAlias($alias);
            $result = $this->api->distributionList->deleteAlias($list);
        }

        return true;
    }


}