<?php

namespace FiloBlu\Flow\Model\From\Entity;

use Exception;
use FiloBlu\Flow\Helper\LoggerProvider;
use Magento\Catalog\Model\ProductFactory;
use Magento\Eav\Model\ConfigFactory;
use Magento\Eav\Model\Entity\Attribute\Source\BooleanFactory;
use Magento\Eav\Model\Entity\AttributeFactory;
use Magento\Eav\Model\Entity\TypeFactory;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Registry;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Model\CustomerFactory as CustomerModelFactory;
use Magento\Customer\Api\Data\CustomerInterfaceFactory AS CustomerFactory;
use FiloBlu\Flow\Helper\Data as HelperData;

/**
 * Class Customer
 * @package FiloBlu\Flow\Model\From\Entity
 */
class Customer extends AbstractEntity
{

    /**
     *
     */
    const EAV_CODE_PASSWORD_HASH = 'password_hash';
    /**
     *
     */
    const EAV_CODE_PASSWORD = 'password';
    /**
     * @var ConfigFactory
     */
    protected $configFactory;
    /**
     * @var CustomerRepositoryInterface
     */
    protected $_customerRepositoryInterface;
    /**
     * @var CustomerFactory
     */
    protected $customerFactory;
    /**
     * @var bool
     */
    public $isCreate = false;

    /**
     * @var HelperData
     */
    protected $helperData;
    /**
     * @var CustomerModelFactory
     */
    protected $customerModelFactory;
    protected $websiteId;
    protected $channelConfig;


    /**
     * @param Registry $registry
     * @param ProductFactory $productFactory
     * @param \FiloBlu\Flow\Helper\Product $helperProduct
     * @param \FiloBlu\Flow\Helper\Attribute $helperAttribute
     * @param LoggerProvider $loggerProvider
     * @param AttributeFactory $attributeFactory
     * @param CollectionFactory $attributeOptionCollectionFactory
     * @param ObjectManagerInterface $objectManager
     * @param ConfigFactory $configFactory
     * @param TypeFactory $entityTypeFactory
     * @param BooleanFactory $booleanFactory
     * @param CustomerRepositoryInterface $customerRepositoryInterface
     * @param CustomerFactory $customerFactory
     * @param CustomerModelFactory $customerModelFactory
     * @param HelperData $helperData
     * @param array $data
     */
    public function __construct(
        Registry $registry,
        ProductFactory $productFactory,
        \FiloBlu\Flow\Helper\Product $helperProduct,
        \FiloBlu\Flow\Helper\Attribute $helperAttribute,
        LoggerProvider $loggerProvider,
        AttributeFactory $attributeFactory,
        CollectionFactory $attributeOptionCollectionFactory,
        ObjectManagerInterface $objectManager,
        ConfigFactory $configFactory,
        TypeFactory $entityTypeFactory,
        BooleanFactory $booleanFactory,
        CustomerRepositoryInterface $customerRepositoryInterface,
        CustomerFactory $customerFactory,
        CustomerModelFactory $customerModelFactory,
        HelperData $helperData,
        array $data = []
    ) {
        parent::__construct(
            $registry,
            $productFactory,
            $helperProduct,
            $helperAttribute,
            $loggerProvider,
            $attributeFactory,
            $attributeOptionCollectionFactory,
            $objectManager,
            $entityTypeFactory,
            $booleanFactory,
            $data
        );
        $this->configFactory = $configFactory;
        $this->_customerRepositoryInterface = $customerRepositoryInterface;
        $this->customerFactory = $customerFactory;
        $this->customerModelFactory = $customerModelFactory;
        $this->helperData = $helperData;
        $this->websiteId = $data['websiteId'];
        $this->channelConfig = $data['channelConfig'];
    }

    /**
     * @return bool|mixed|null
     * @throws Exception
     */
    public function getObjectId()
    {
        return $this->_objectEntityId;
    }

    /**
     * @return mixed|void
     * @throws Exception
     */
    public function process()
    {
        if ($this->isSpecialFunction($this->attributeCode)) {
            $this->processSpecialFunction();
            return;
        }

        return $this->getObject();
    }

    /**
     * @return mixed
     */
    protected function getObject(){
        $this->isCreate = false;
        try {
            $customerFromRepo = $this->_customerRepositoryInterface->get($this->entityIdentifier,$this->websiteId);
            if($customerFromRepo->getId()) {
                $customer = $this->customerModelFactory->create()->load($customerFromRepo->getId());
            }
        } catch (\Exception $e){
            $customer = $this->customerModelFactory->create();
            $this->isCreate = true;
        }
        $this->_objectEntityId = $customer->getId();
        return $customer;
    }

    /**
     * @return mixed
     * @throws Exception
     */
    protected function processSpecialFunction()
    {
        $specificSpecialClass = $this->objectManager->create($this->getSpecialActionClassName());

        if (!method_exists($specificSpecialClass, 'process')) {
            throw new Exception('Missing special function for attribute ' . $this->attributeCode);
        }

        return $specificSpecialClass->process($this->getObject(), $this->attributeValue, $this->storeId, $this->channelConfig);
    }

}
