<?php
/**
* @author OfficeBrain 4160 <info@officebrain.com>
*
* Description :  Transaction Queue Extended Class
*
**/
namespace OfficeBrain\Bundle\QueueBundle\Manager\Extended;

use OfficeBrain\Bundle\QueueBundle\Manager\AbstractManager\QueueAbstract;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use OfficeBrain\Bundle\QueueBundle\Document\TransactionQueue;

class TransactionQueueExtended extends QueueAbstract
{
    protected $container;
    protected $entityParameters;
    
    public function __construct(Container $container, $entityParameters)
    {
        $this->container = $container;
        $this->entityParameters = $entityParameters;
        $this->sessionManager = $this->container->get('office_brain_session_manager');
        $this->dm = $container->get('doctrine_mongodb')->getManager();
        $this->em = $container->get('doctrine')->getManager();
        $this->repository = $this->dm->getRepository('OfficeBrainQueueBundle:TransactionQueue');
        $this->request = $this->container->get('request');
        $this->projectSetting = $this->request->get('project_setting');
        $this->projectUserSetting = $this->request->get('project_user_setting');
        $this->emailManager = $container->get('office_brain_email_service');
        $this->translator = $container->get('translator');
        $this->setUserProjectSettings = array('Quote', 'QuoteItemLine', 'Order');
    }
    
    public function mapQueue($action, $data, $type='json')
    {
        if($this->projectSetting['instance_type']!="sub_shop")
        {
            $object = $this->request->attributes->get('object');
            if ($action == 'remove') {
                $formatedData = parent::formatData($data, $type);
            } else {
                $formatedData = $this->processData($data, $this->entityParameters[$object], $type);
            }
            if (is_array($formatedData) && array_key_exists('exception', $formatedData)) {
                $this->setQueue($object, $action, array(), $formatedData['exception']);
            } else {
                $formatedData = array('scalar' => $formatedData);
                $this->setQueue($object, $action, $formatedData);
            }
        }
    }
    
    /**
    * @author Employee Id: 4160
    * Description :
    * setQueue method to set values in queue
    *
    * @param 1 : string name name of supplier or distributor
    * @param 2 : string object object name of entity
    * @param 3 : string action action name to perform
    * @param 4 : array args fields mapping arguments
    *
    * @return object
    *
    **/
    public function setQueue($object, $action, $args, $msg=null)
    {
        $queueObj = new TransactionQueue();
        $date = parent::setDateFormat();
        try {
            $queueObj->setFrom(1);
            $queueObj->setInstanceId($this->projectSetting['instance_id']);
            $queueObj->setInstanceType($this->projectSetting['instance_type']);
            $queueObj->setObjectName($object);
            $queueObj->setAction($action);
            $queueObj->setPriority(0);
            $queueObj->setCreatedAt($date);
            $queueObj->setUpdatedAt($date);
            if ($msg == null) {
                $queueObj->setArgs($args);
                $queueObj->setStatus('New');
            } else {
                $queueObj->setStatus('Error');
                $queueObj->setMessage($msg);
            }
            $queue = $this->repository->save($queueObj);
            if ($msg) {
                $db_name = $this->container->getParameter('mongodb_database');
                $db_server_name = $this->container->getParameter('mongodb_server');
                $params = array('message' => $msg, 'queueName' => 'TransactionQueue', 'queueData' => $queueObj,'db_name' => $db_name,'db_server_name' => $db_server_name);
                $this->emailManager->sendMail('error_queue', $this->container->getParameter('mongo_error_email'), $params);
            }
            return $queue;
        } catch (\Exception $e) {
           if ($msg == null) {
               $status ='New';
            } else {
                $status ='Error';
            }
           $queueData= '{ from : "1",</br>
               instance_id : "'.$this->projectSetting['instance_id'].'",</br>
               instance_type : "'.$this->projectSetting['instance_type'].'",</br>
               objectName : "'.$object.'",</br>
               action : "'.$action.'",</br>
               priority : 0,</br>
               created_at :"'.$date->format("Y-m-d H:i:s").'",</br>
               updated_at : "'.$date->format("Y-m-d H:i:s").'",</br>
               args : '.json_encode($args).',</br>
               status : "'.$status.'"</br>
           }';
            $params = array('message' => $e->getMessage(), 'queueName' => 'TransactionQueue','queueData' => $queueData);
            $this->emailManager->send($this->container->getParameter('mongo_error_email'), $this->container->getParameter('mailer_user'), $e->getMessage(), $queueData);
        }
    }

    /**
    * @author Employee Id: 4160
    * Description :
    * processData method to data mapping process
    *
    * @param 1 : array data data array of keys and values
    * @param 2 : array configObject configuration parameters of object with dataMapping fields, methods, parameters
    * @param 3 : string type type of formatting
    *
    * @return array
    *
    **/
    public function processData($entityORM, $configObject, $type="json")
    {
        try {
            $serialize = $this->container->get('jms_serializer');
            $dataSerialize = json_decode($serialize->serialize($entityORM, 'json'), true);
            $resultData = parent::formatData($dataSerialize, $type);
            return $resultData;
        } catch (\Exception $e) {
            return array('exception' => $e->getMessage());
        }
    }
    
    /**
    * @author Employee Id: 4160
    * Description :
    * processOnResult method to process on result data
    *
    * @param 1 : object or array of result
    * @param 2 : object of document
    * @param 3 : string action name
    * @param 4 : string object name
    * @param 5 : array of data
    * @param 6 : array of field names
    * 
    * @return
    *
    **/
    public function processOnResult($result, $document, $action, $object, $decodeData, $returnField, $noErpField=0)
    {
        if ($result) {
            if (array_key_exists('exception', $result) && array_key_exists('status', $result) && $result['status'] == 'Error') {
                echo "\n\n ", $result['message'];
                echo "\n Exception from Result...\n Exception Error in Service Manager on Return result so terminated transaction queue...\n";
                $this->setStatusData($document, 'Error', $result['message'], $decodeData);
                die;
            }
            $returnFieldData = array();
            //if ($action == 'create' || $action == 'update') {
            if ($action == 'create') {
                if (gettype($result) == 'object' && $noErpField == 0) {
                    if ($result->getErpId()) {
                        $this->setDateData($action, $object, $result, $decodeData);
                        $this->request->attributes->set('object', $object);
                        $this->request->attributes->set('instance_id', $document->getInstanceId());
                        $this->mapQueue('update', $result);
                        if (count($returnField) > 0) {
                            foreach ($returnField as $key => $value) {
                                $returnMethod = 'get'.$key;
                                $returnFieldData[$value] = $result->$returnMethod();
                            }
                        }
                    }
                } elseif (gettype($result) == 'array' && $noErpField == 0) {
                    $entityData = $result['data'];
                    if ($entityData->getErpId()) {
                        $this->setDateData($action, $object, $entityData, $decodeData);
                        $this->request->attributes->set('object', $object);
                        $this->request->attributes->set('instance_id', $document->getInstanceId());
                        $this->mapQueue('update', $entityData);
                        if (count($returnField) > 0) {
                            foreach ($returnField as $key => $value) {
                                $returnMethod = 'get'.$key;
                                $returnFieldData[$value] = $entityData->$returnMethod();
                            }
                        }
                    }
                } else {
                    if (gettype($result) == 'array') {
                        $entityData = $result['data'];
                    } else if (gettype($result) == 'object') {
                        $entityData = $result;
                    }
                    if (count($returnField) > 0) {
                        foreach ($returnField as $key => $value) {
                            if ($key != 'ErpId') {
                                $returnMethod = 'get'.$key;
                                if ($entityData) $returnFieldData[$value] = $entityData->$returnMethod();
                            }
                        }
                    }
                }
            }
            $this->setStatusData($document, 'Success', 'Successfully Implemented');
            return $returnFieldData;
        } else {
            $this->setStatusData($document, 'Error', 'Error in result of manager service ', $decodeData);
            echo "\n Error in Service Manager on Return result so terminated transaction queue...\n";
            die;
            break;
        }
    }
    
    /**
    * @author Employee Id: 4160
    * Description :
    * processRunQueue method to read records from queue and update status
    *
    * @param 1 : string name name of supplier or distributor or association
    * @param 2 : integer count count of jobs to execute in batch
    *
    * @return
    *
    **/
    public function processRunQueue($instance_id, $count)
    {
        $progressResult = $this->repository->findInProgressJobs(intval($instance_id));
        if (count($progressResult) > 0) {
            echo "\n In Progress jobs are running so terminated transaction queue...";
            die;
        }
        $cursorResult = $this->repository->findRunJobs(intval($instance_id), $count);
        try {
            if (count($cursorResult) > 0) {
                foreach ($cursorResult as $document) {
                    $status = $document->getStatus();
                    if ($status == 'Error') {
                        echo "\n Error job record found so terminated transaction queue...";
                        die;
                    }
                    $date = parent::setDateFormat();
                    $document->setStarted($date);
                    $document->setStatus('In Progress');
                    $this->repository->save($document);
                    
                    $action = $document->getAction();
                    $object = $document->getObjectName();
                    $args = $document->getArgs();
                    $id = $document->getId();
                    $instance_id = $document->getInstanceId();
                    $decodeData = (array) json_decode($args['scalar']);
                    if (count($decodeData) == 0) {
                        echo "\n\n Not proper formatted data in Record Id ($id) of Transaction Queue so terminated transaction queue...\n";
                        die;
                    }
                    $accessListener = $this->container->get('office_brain_access_management.access_configuration');
                    $this->request->attributes->set('user_id', null);
                    if (in_array($object, $this->setUserProjectSettings)) {
                        $this->request->attributes->set('user_id', $decodeData['user_id']);
                    }
                    $accessListener->PrepareAccessAndConfigurationRulesForCli ($this->request);
                    $this->processExecuteAction($object, $action, $decodeData, $document);
                }
            } else {
                echo "\n No jobs are to execute in transaction queue...";
                die;
            }
        } catch (\Exception $e) {
            echo "\n Error in Transaction Queue Records...\n", $e->getMessage();
            echo "\n Error line : ", $e->getLine(), $e->getTraceAsString(), $e->getFile(), $e->getCode();
            die;
        }
    }
    
    /**
    * @author Employee Id: 4160
    * Description :
    * processExecuteAction method to execute action based on recordData of Queue
    *
    * @param 1 : string object object key name
    * @param 2 : string action action to perform
    * @param 3 : formatted args key values dataArray
    *
    * @return object or array
    *
    **/
    public function processExecuteAction($object, $action, $decodeData, $document)
    {
        if (array_key_exists($object, $this->entityParameters)) {
            $configObject = $this->entityParameters[$object];
            if ($action == 'create' || $action == 'update') {
                list($entityStatus, $action, $entityName, $entityORM, $msg) = $this->getEntityDetails($configObject, $action, $decodeData);
                if ($action == 'update') {
                    if (!array_key_exists('id', $decodeData)) {
                        $decodeData['id'] = $entityORM->getId();
                    }
                }
                if ($entityStatus == 'Error') {
                    $result = array('exception' => 1, 'status' => 'Error', 'message' => $msg);
                    return $this->processOnResult($result, $document, $action, $object, $decodeData, array());
                }
            }
            $relationalData = $this->processRelationalData($configObject[$action], $decodeData);
            $decodeData = $relationalData[0];
            $ignoreFormParameter = $relationalData[1];
            
            $method = $configObject[$action]['method'];
            $service = $configObject[$action]['service'];
            
            if (!$method) {
                $result = array('exception' => 1, 'status' => 'Error', 'message' => "No method configured for $action action of object $object in transaction queue...");
                return $this->processOnResult($result, $document, $action, $object, $decodeData, array());
            }
            
            if (array_key_exists('culture', $decodeData)) {
                $this->request->attributes->set('locale', $decodeData['culture']);
            }
            
            if ($action == 'remove' || $action == 'updateStatus') {
                return $this->processMethodExecute($action, $service, $method, $decodeData);
            }
            $formTypeData = $configObject[$action]['formType'];
            $fromTypeResult = null;
            $methodResult = array();
            $formEntitiesORM = array();
            $formFlag = 1;
            if (count($formTypeData) == 0) $formFlag = 0;
            if (array_key_exists('methods', $formTypeData)) {
                foreach ($formTypeData['methods'] as $key => $value) {
                    $methodName = $formTypeData['methods'][$key]['name'];
                    $finalData = array();
                    if (array_key_exists('parameters', $formTypeData['methods'][$key])) {
                        $parameters = $formTypeData['methods'][$key]['parameters'];
                        foreach ($parameters as $parameterKey => $parameterValue) {
                            if (is_array($parameters[$parameterKey])) {
                                foreach ($parameters[$parameterKey] as $dataKey => $dataValue) {
                                  if (array_key_exists($dataValue, $decodeData)) {
                                        $finalData[$parameterKey][$dataValue] = $decodeData[$dataValue];
                                    }
                                }
                            } else {
                                if (array_key_exists($parameterValue, $decodeData)) {
                                    $finalData[$parameterKey] = $decodeData[$parameterValue];
                                } elseif ($parameterKey == 'container') {
                                    $finalData[$parameterKey] = $this->container;
                                } elseif ($parameterKey == 'request') {
                                    $finalData[$parameterKey] = $this->request;
                                } elseif ($parameterKey == 'return') {
                                    if (array_key_exists($parameters[$parameterKey], $methodResult)) {
                                        $finalData[$parameterKey] = $methodResult[$parameters[$parameterKey]];
                                    }
                                }
                            }
                        }
                    }
                    
                    try {
                        $methodService = $formTypeData['methods'][$key]['service'];
                        $methodServiceManager = $this->container->get($methodService);
                        $fromTypeResult = call_user_func_array(array($methodServiceManager, $methodName), $finalData);
                        $methodResult[$methodName] = $fromTypeResult;
                    } catch (\Exception $e) {
                        $result = array('exception' => 1, 'status' => 'Error', 'message' => $e->getMessage(). "\n Error in Service Manager of method $methodName for $action so terminated transaction queue...");
                        return $this->processOnResult($result, $document, $action, $object, $decodeData, array());
                    }
                }
            }

            $parametersType = array();
            if (array_key_exists('parameters', $formTypeData)) {
                $parameters = $formTypeData['parameters'];
                if ($ignoreFormParameter != null) {
                    if(in_array($ignoreFormParameter, $parameters)) {
                        unset($parameters[$ignoreFormParameter]);
                    }
                }
                $parametersType = $this->setProcessParameters($parameters, $decodeData, $methodResult);
            }
            $checkFields = array();
            if (array_key_exists('checkFields', $formTypeData)) {
                foreach ($formTypeData['checkFields'] as $key => $value) {
                    if (array_key_exists($key, $methodResult)) {
                        $checkFields = $methodResult[$key][$value];
                    }
                }
            }
            
            if ($formFlag == 1) {
                $formType = $formTypeData['name'];
                try {
                    $r = new \ReflectionClass($formType);
                    $formTypeObj = $r->newInstanceArgs($parametersType);
                } catch (\Exception $e) {
                    $result = array('exception' => 1, 'status' => 'Error', 'message' => $e->getMessage()."\n Error in Form Build Class Run transaction queue...");
                    return $this->processOnResult($result, $document, $action, $object, $decodeData, array());
                }
            }
            $this->setDateData($action, $object, $entityORM, $decodeData);
            $form = null;
            if ($formFlag == 1) {
                if (array_key_exists('formEntities', $configObject[$action])) {
                    $formEntitiesORM = $this->processFormEntities($action, $configObject[$action]['formEntities'], $decodeData);
                }
                if (count($formEntitiesORM) > 0) {
                    $form = $this->container->get('form.factory')->create($formTypeObj, $formEntitiesORM, array('csrf_protection' => false));   
                } else {
                    $form = $this->container->get('form.factory')->create($formTypeObj, $entityORM, array('csrf_protection' => false));
                }
            }
            $data = array();
            $dataMappingFields = $configObject['queueDataMapping'];
            $ignoreFields = $configObject[$action]['ignoreFields'];
            $addFields = $configObject[$action]['addFields'];
            foreach ($dataMappingFields as $key => $value) {
                if (array_key_exists($key, $decodeData)) {
                    # TO DO improve code for data for nested arrays
                    if (is_array($value)) {
                        if (array_key_exists($key, $this->entityParameters)) {
                            return $this->processExecuteAction($key, $action, $value);
                        }
                    } else {
                        if (!in_array($key, $ignoreFields) && !in_array($key, $addFields)) {
                            if ($key == 'erp_id' || $key == 'status' || (count($checkFields) > 0 && array_key_exists($value, $checkFields) && $checkFields[$value]->admin == 1)) {
                                $data[$value] = $decodeData[$key];
                            } else if (count($checkFields) == 0) {
                                $data[$value] = $decodeData[$key];
                            }
                        }
                    }
                }
            }
            try {
                if ($formFlag == 1) {
                    if (count($formEntitiesORM) > 0) {
                        foreach (array_keys($formEntitiesORM) as $formEntitieskey => $formEntitiesvalue) {
                            $dataFields = $data;
                            $fields = array();
                            foreach ($form[$formEntitiesvalue]->all() as $child) {
                                if (!$child->isValid()) {
                                    $fields[] = $child->getName();
                                }
                            }
                            foreach ($dataFields as $dataKey => $datavalue) {
                                if (!in_array($dataKey, $fields)) {
                                    unset($dataFields[$dataKey]);
                                }
                            }
                            $form[$formEntitiesvalue]->bind($dataFields);
                            if (!$form[$formEntitiesvalue]->isValid()) {
                                $result = array('exception' => 1, 'status' => 'Error', 'message' => $form[$formEntitiesvalue]->getErrorsAsString().' Invalid Form...');
                                return $this->processOnResult($result, $document, $action, $object, $decodeData, array());
                            }
                        }
                    } else {
                        $fields = array();
                        foreach ($form->all() as $child) {
                            if (!$child->isValid()) {
                                $fields[] = $child->getName();
                            }
                        }
                        foreach ($data as $dataKey => $datavalue) {
                            if (!in_array($dataKey, $fields)) {
                                unset($data[$dataKey]);
                            }
                        }
                        $form->bind($data);
                        if (!$form->isValid()) {
                            $result = array('exception' => 1, 'status' => 'Error', 'message' => $form->getErrorsAsString().' Invalid Form...');
                            return $this->processOnResult($result, $document, $action, $object, $decodeData, array());
                        }
                    }
                }
                $methodParameters = array();
                if (array_key_exists('methodParameters', $configObject[$action])) {
                    $parameters = $configObject[$action]['methodParameters'];
                    $methodParameters = $this->setProcessParameters($parameters, $decodeData, array(), $form);
                }
                $actionBeforeResult = $this->actionBeforemethod($configObject[$action], $document, $decodeData, $form);
                if ($configObject[$action]['beforeResultUse'] == 1) {
                    $methodParameters[] = $actionBeforeResult;
                }
                $serviceManager = $this->container->get($service);
                $result = call_user_func_array(array($serviceManager, $method), $methodParameters);
                $returnField = array();
                $returnFieldData = array();
                if (array_key_exists('mainResultField', $configObject[$action])) {
                    $returnField = $configObject[$action]['mainResultField'];
                }
                $noErpField = 0;
                if (array_key_exists('noErpField', $configObject) && $configObject['noErpField']) {
                    $noErpField = $configObject['noErpField'];
                }
                $returnFieldData = $this->processOnResult($result, $document, $action, $object, $decodeData, $returnField, $noErpField);
                $actionAfterResult = $this->actionAftermethod($configObject[$action], $document, $decodeData, $form, $returnFieldData);
            } catch (\Exception $e) {
                $result = array('exception' => 1, 'status' => 'Error', 'message' => $e->getMessage().' Error in Run transaction queue...'.$e->getLine(). $e->getFile());
                return $this->processOnResult($result, $document, $action, $object, $decodeData, array());
            }
        }
    }

    /**
    * @author Employee Id: 4160
    * Description :
    * processFormEntities method to process on form entities
    *
    * @param 1 : string action
    * @param 2 : array formEntities
    * @param 3 : array decodeData
    *
    * @return
    *
    **/
    public function processFormEntities($action, $formEntities, $decodeData) {
        $formEntitiesArray = array();
        foreach ($formEntities as $key => $value) {
            foreach ($value as $k => $v) {
                if ($action == 'create') {
                    if(array_key_exists('key', $value)) {
                        $formEntitiesArray[$value['key']] = new $value['value'](); 
                    } else {
                        $formEntitiesArray[] = new $value['value']();
                    }
                } else {
                    $entityORMResult = array();
                    foreach ($value['parameters'] as $parameterKey => $parameterValue) {
                        if (array_key_exists($parameterValue, $decodeData)) {
                            $method = 'findOneBy'.$parameterKey;
                            $entityORMResult = $this->em->getRepository($value['bundle'].':'.$value['entity'])->$method(array($parameterValue => $decodeData[$parameterValue]));
                            if (count($entityORMResult) > 0) break;
                        }
                    }
                    if(array_key_exists('key', $value)) {
                        $formEntitiesArray[$value['key']] = $entityORMResult; 
                    } else {
                        $formEntitiesArray[] = $entityORMResult;
                    }
                }
            }
        }
        return $formEntitiesArray;
    }

    /**
    * @author Employee Id: 4160
    * Description :
    * setStatusData method to set status and dates of mongodb document
    *
    * @param 1 : object document mongodb document
    * @param 2 : string status status to update
    * @param 3 : string message message update to document
    *
    * @return
    *
    **/
    public function setStatusData($document, $status, $message, $data=array())
    {
        $finishedDate = parent::setDateFormat();
        $document->setUpdatedAt($finishedDate);
        $document->setFinished($finishedDate);
        $document->setStatus($status);
        $document->setMessage($message);
        $this->repository->save($document);
        if ($status == 'Error') {
            $ddata = json_encode($data);
            $db_name = $this->container->getParameter('mongodb_database');
            $db_server_name = $this->container->getParameter('mongodb_server');
            $params = array('message' => $message, 'queueName' => 'TransactionQueue', 'queueData' => $ddata,'db_name' => $db_name,'db_server_name' => $db_server_name);
            $this->emailManager->sendMail('error_queue', $this->container->getParameter('mongo_error_email'), $params, $this->projectSetting['culture_id']);
        }
    }
    
    /**
    * @author Employee Id: 4160
    * Description :
    * setDateData method to set date values into entity
    *
    * @param 1 : string action name
    * @param 2 : string object name
    * @param 3 : object entity
    * @param 4 : array decodeData
    *
    * @return boolean
    *
    **/
    public function setDateData($action, $object, $entity, $decodeData)
    {
        if (array_key_exists($object, $this->entityParameters)) {
            $configObject = $this->entityParameters[$object];
            $addFields = $configObject[$action]['addFields'];
            if (count($addFields) == 0) {
                return true;
            }
            foreach ($addFields as $key => $value) {
                if (array_key_exists($key, $decodeData) && ($decodeData[$key])) {
                    $setMethod = 'set'.$value;
                    if ($decodeData[$key] != 'False') {
                        $date = parent::setDateFormat($decodeData[$key]);
                        $entity->$setMethod($date);
                    }
                    /*if ($action == "update") {
                        $this->em->persist($entity);
                        $this->em->flush();
                    }*/
                }
            }
        }
    }
    
    /**
    * @author Employee Id: 4160
    * Description :
    * setProcessParameters method to process on parameters and return array
    *
    * @param 1 : array parameters
    * @param 2 : array decodeData
    * @param 3 : array methodResult
    * @param 4 : object form
    *
    * @return array
    *
    **/
    public function setProcessParameters($parameters, $decodeData, $methodResult, $form=null, $flag=TRUE)
    {
        $keyFlag = FALSE;
        $methodParameters = array();
        foreach ($parameters as $key => $value) {
            if (is_array($parameters[$key])) {
                $methodParameters = $this->setProcessParameters($parameters[$key], $decodeData, $methodResult, $form, FALSE);
                if (array_key_exists('required_key', $parameters)) {
                    $methodParameters[$key] = $methodParameters[0];
                }
                return $methodParameters;
            }
            if (array_key_exists($key, $decodeData)) {
                if (array_key_exists('required_key', $parameters) && $parameters['required_key'] == 1) {
                    if (is_object($decodeData[$key])) {
                        $decodeData[$key] = (array) $decodeData[$key];
                    }
                    if (is_array($decodeData[$key])) {
                        $methodParameters[$value] = $decodeData[$key];
                    } else {
                        $methodParameters[$value] = $decodeData[$key];
                    }
                }
                else $methodParameters[] = $decodeData[$key];
            } elseif (array_key_exists($key, $methodResult)) {
                $methodParameters[] = $methodResult[$key];
            } elseif ($key == 'container') {
                $methodParameters[] = $this->container;
            } elseif ($key == 'request') {
                $methodParameters[] = $this->request;
            } elseif ($key == 'formContent' && $value == 'Data') {
                $methodParameters[] = $form->getData();
            } elseif ($key == 'formContent' && $value == 'Object') {
                $methodParameters[] = $form;
            } elseif($key != '' && $value == 'all') {
                $decodeData = (array) json_decode(json_encode($decodeData), true);
                $methodParameters[$key] = $decodeData;
            } elseif ($key == 'service') {
                $methodParameters[$key] = $this->container->get($value);
            } else {
                if (array_key_exists('key', $parameters) && $parameters['key'] == 1) {
                    $keyFlag = TRUE;
                }
                if (array_key_exists('required_key', $parameters) && $parameters['required_key'] == 1 && $key != 'required_key' && $key != 'key') {
                    if ($keyFlag == TRUE) {
                        $methodParameters[$key] = $value;
                    } else {
                        $methodParameters[$value] = $value;
                    }
                }
                else {
                    if ($key != 'required_key' && $key != 'key') {
                        if ($keyFlag == TRUE) {
                            $methodParameters[$key] = $value;
                        } else {
                            $methodParameters[] = $value;
                        }
                    }
                }
            }
        }
        if (!$flag) {
            $methodP[] = $methodParameters;
            return $methodP;
        }
        return $methodParameters;
    }
    
    /**
    * @author Employee Id: 4160
    * Description :
    * getEntityDetails method to return entity name and entity object
    *
    * @param 1 : array configObject
    * @param 2 : array action
    * @param 3 : array decodeData
    *
    * @return array entity name and entity object
    *
    **/
    public function getEntityDetails($configObject, $action, $decodeData)
    {
        $bundle = $configObject['bundle'];
        $status = null;
        $noErpField = 0;
        if (array_key_exists('noErpField', $configObject)) {
            $noErpField = $configObject['noErpField'];
        }
        $entity = $configObject[$action]['entity'];
        $conditionalFields = array();
        if (array_key_exists('conditionalFields', $configObject[$action])) {
            $conditionalFields = $configObject[$action]['conditionalFields'];
        }
        $elements = explode('\\', $entity);
        $entityName = $elements[count($elements)-1];
        if ($action == 'create') {
            if (array_key_exists('erp_id', $decodeData) && isset($decodeData['erp_id']) && $noErpField == 0) {
                $fieldsArray = array();
                $fieldsArray['erpId'] = $decodeData['erp_id'];
                foreach ($conditionalFields as $conditionalKey => $conditionalValue) {
                    if (array_key_exists($conditionalKey, $decodeData) && isset($decodeData[$conditionalKey])) {
                        if (is_object($decodeData[$conditionalKey])) {
                            $decodeData[$conditionalKey] = (array) json_decode(json_encode($decodeData[$conditionalKey]), true);
                        }
                        if (is_array($decodeData[$conditionalKey])) {
                            $key = array_keys($decodeData[$conditionalKey])[0];
                            $decodeData[$conditionalKey] = $decodeData[$conditionalKey][$key];
                        }
                        $fieldsArray[$conditionalValue] = $decodeData[$conditionalKey];
                    }
                }
                if (array_key_exists('erp', $conditionalFields) && $conditionalFields['erp'] == 0) {
                    unset($fieldsArray['erpId']);
                }
                $entityORM = $this->em->getRepository($bundle.':'.$entityName)->findOneBy($fieldsArray);
                if ($entityORM) {
                    $status = 'Success';
                    $action = 'update';
                    $msg = null;
                } else {
                    $entityORM = new $entity();
                    $status = 'Success';
                    $msg = null;
                }
            } else if ($noErpField == 1 && array_key_exists('noErpFieldData', $configObject)) {
                $noErpFieldData = $configObject['noErpFieldData'];
                $erpBundleName = $noErpFieldData['bundleName'];
                $erpEntityName = $noErpFieldData['entityName'];
                $erpDataField = $noErpFieldData['dataField'];
                if (array_key_exists($erpDataField, $decodeData)) {
                    $entityORM = $this->em->getRepository($erpBundleName.':'.$erpEntityName)->findOneByErpId($decodeData[$erpDataField]);
                    if ($entityORM) {
                        $status = 'Success';
                        $action = 'update';
                        $msg = null;
                    } else {
                        $entityORM = new $entity();
                        $status = 'Success';
                        $msg = null;
                    }
                } else {
                    $status = 'Error';
                    $msg = "Not found $erpDataField from Record from table so terminated transaction queue...";
                }
            } else {
                $entityORM = new $entity();
                $status = 'Success';
                $msg = null;
            }
        } elseif ($action == 'update') {
            $fieldsArray = array();
            if (array_key_exists('id', $decodeData) && isset($decodeData['id'])) {
                $id = $decodeData['id'];
                $fieldsArray['id'] = $decodeData['id'];
                foreach ($conditionalFields as $conditionalKey => $conditionalValue) {
                    if (array_key_exists($conditionalKey, $decodeData) && isset($decodeData[$conditionalKey])) {
                        $fieldsArray[$conditionalValue] = $decodeData[$conditionalKey];
                    }
                }
                $entityORM = $this->em->getRepository($bundle.':'.$entityName)->findOneBy($fieldsArray);
                if (!$entityORM) {
                    $status = 'Error';
                    $msg = "Not found Record for Id $id from table so terminated transaction queue...";
                } else {
                    $status = 'Success';
                    $msg = null;
                }
            }
        }
        return array($status, $action, $entityName, $entityORM, $msg);
    }

    /**
    * @author Employee Id: 4160
    * Description :
    * processMethodExecute method to execute action for remove and updateStatus
    *
    * @param 1 : string action
    * @param 2 : string service name
    * @param 3 : string method
    * @param 3 : array decodeData
    *
    * @return object | array
    *
    **/
    public function processMethodExecute($action, $service, $method, $decodeData)
    {
        $serviceManager = $this->container->get($service);
        if ($action == 'updateStatus') {
            if (array_key_exists('status', $decodeData) && isset($decodeData['status'])) {
                $result = $serviceManager->$method($decodeData['id'], $decodeData['status']);
                return $result;
            }
        } elseif ($action == 'remove') {
            if (array_key_exists('id', $decodeData) && isset($decodeData['id'])) {
                $result = $serviceManager->$method($decodeData['id']);
                return $result;
            }
        }
        return array();
    }
    
    /**
    * @author Employee Id: 4160
    * Description :
    * processRelationalData method to process data for relational fields and replaced by relational id
    *
    * @param 1 : array configObject
    * @param 2 : array decodeData
    *
    * @return array decodeData
    *
    **/
    public function processRelationalData($configActionObject, $decodedata) {
        $ignoreFormParameterResult = FALSE;
        if (array_key_exists('relationalFields', $configActionObject)) {
            $relationalFields = $configActionObject['relationalFields'];
            foreach ($relationalFields as $key => $value) {
                $fieldKeys = array_keys($value);
                foreach ($fieldKeys as $k => $v) {
                    if (array_key_exists($v, $decodedata)) {
                        $entityName = $value[$v]['entityName'];
                        $bundleName = $value[$v]['bundleName'];
                        $entityRepositoryName = $value[$v]['repositoryName'];
                        $methodName = $value[$v]['methodName'];
                        $fieldName = $value[$v]['fieldName'];
                        $conditionalFlag = FALSE;
                        if (array_key_exists('ignoreConditionField', $value[$v])) {
                            $conditionalFlag = TRUE;
                            $conditionalFieldName = $value[$v]['ignoreConditionField'];
                            $conditionalFieldValue = $value[$v]['ignoreConditionValue'];
                            $ignoreFormParameter = $value[$v]['ignoreFormParameter'];
                            $ignoreField = $value[$v]['ignoreField'];   
                        }
                        
                        if (is_object($decodedata[$v])) {
                            if (array_key_exists('id', $decodedata[$v]) && isset($decodedata[$v]->id) && $decodedata[$v]->id > 0) {
                                $decodedata[$v] = $decodedata[$v]->id;
                                if ($conditionalFlag == TRUE) {
                                    $entityObj = $this->em->getRepository($bundleName.':'.$entityName)->find($decodedata[$v]);
                                    $conditionalMethod = 'get'.$conditionalFieldName;
                                    if ($entityObj->$conditionalMethod() == $conditionalFieldValue) {
                                        $ignoreFormParameterResult = $ignoreFormParameter;
                                        unset($decodedata[$ignoreField]);
                                    }
                                }
                            } else if(array_key_exists('erp_id', $decodedata[$v]) && isset($decodedata[$v]->erp_id)) {
                                $entityRelationalObject = $this->em->getRepository($bundleName.':'.$entityName)->$methodName($decodedata[$v]->$fieldName);
                                if (count($entityRelationalObject) > 0) {
                                    $decodedata[$v] = $entityRelationalObject[0]->getId();
                                }
                            }
                        } else if (is_array($decodedata[$v])) {
                            if (is_array($decodedata[$v]) && array_key_exists('id', $decodedata[$v]) && isset($decodedata[$v]['id']) && $decodedata[$v]['id'] > 0) {
                                $decodedata[$v] = $decodedata[$v]['id'];
                                if ($conditionalFlag == TRUE) {
                                    $entityObj = $this->em->getRepository($bundleName.':'.$entityName)->find($decodedata[$v]);
                                    $conditionalMethod = 'get'.$conditionalFieldName;
                                    if ($entityObj->$conditionalMethod() == $conditionalFieldValue) {
                                        $ignoreFormParameterResult = $ignoreFormParameter;
                                        unset($decodedata[$ignoreField]);
                                    }
                                }
                            } else if(array_key_exists('erp_id', $decodedata[$v]) && isset($decodedata[$v]['erp_id'])) {
                                $entityRelationalObject = $this->em->getRepository($bundleName.':'.$entityName)->$methodName($decodedata[$v]->$fieldName);
                                if (count($entityRelationalObject) > 0) {
                                    $decodedata[$v] = $entityRelationalObject[0]->getId();
                                }
                            }
                        }
                   }
                }
            }
        }
        return array($decodedata, $ignoreFormParameterResult);
    }

    /**
    * @author Employee Id: 4160
    * Description :
    * actionAftermethod method to process after action executed call methods
    *
    * @param 1 : array configObject
    * @param 2 : object document
    * @param 3 : object form
    *
    * @return array
    *
    **/
    public function actionAftermethod($configObject, $document, $decodeData, $form=null, $returnFieldData=array()) {
        $result = FALSE;
        if (array_key_exists('afterMethods',  $configObject)) {
            foreach ($configObject['afterMethods'] as $key => $value) {
                $afterServiceManager = $this->container->get($value['service']);
                $afterMethodParamateres = array();
                $afterParameters = $value['parameters'];
                foreach ($afterParameters as $k => $v) {
                    if($k == 'formContent' && $form!=null) {
                        if ($afterParameters[$k] == 'Object') {
                            $afterMethodParamateres[] = $form;
                        } else if ($afterParameters[$k] == 'Data') {
                            $afterMethodParamateres[] = $form->getData();
                        }
                    }
                    elseif($k == 'translatorMessage') {
                        $afterMethodParamateres[] = $this->translator->trans($afterParameters[$k]);
                    }
                    else {
                        if(is_array($afterParameters[$k])) {
                            $afterMethodParamateres[] = $this->setProcessParameters($afterParameters[$k], $decodeData, array());
                        } else {
                            if (array_key_exists($k, $decodeData)) {
                                $afterMethodParamateres[] = $decodeData[$k];
                            } else {
                                $afterMethodParamateres[] = $afterParameters[$k];
                            }
                        }
                    }
                }
                if (count($returnFieldData) > 0) {
                    if (count($afterMethodParamateres) == 1) {
                        $afterMethodParamateres[0] = array_merge($afterMethodParamateres[0], $returnFieldData);
                    } else {
                        $afterMethodParamateres = array_merge($afterMethodParamateres, $returnFieldData);
                    }
                }
                try {
                    $result = call_user_func_array(array($afterServiceManager, $value['name']), $afterMethodParamateres);
                } catch (\Exception $e) {
                    return $this->setStatusData($document, 'Error', $e->getMessage().' Error in after action method execution...');
                }
            }
        }
        return $result;
    }

     /**
    * @author Employee Id: 4834
    * Description :
    * actionBeforemethod method to process before action executed call methods
    *
    * @param 1 : array configObject
    * @param 2 : object document
    * @param 3 : object form
    *
    * @return array
    *
    **/
    public function actionBeforemethod($configObject, $document, $decodeData, $form=null) {
        $result = FALSE;
        if (array_key_exists('beforeMethods',  $configObject)) {
            foreach ($configObject['beforeMethods'] as $key => $value) {
                $beforeServiceManager = $this->container->get($value['service']);
                $beforeMethodParamateres = array();
                $beforeParameters = $value['parameters'];
                foreach ($beforeParameters as $k => $v) {
                    if($k == 'formContent' && $form!=null) {
                        if ($beforeParameters[$k] == 'Object') {
                            $beforeMethodParamateres[] = $form;
                        } else if ($beforeParameters[$k] == 'Data') {
                            $beforeMethodParamateres[] = $form->getData();
                        }
                    } elseif($k == 'translatorMessage') {
                        $beforeMethodParamateres[] = $this->translator->trans($beforeParameters[$k]);
                    } else {
                        if(is_array($beforeParameters[$k])) {
                            $beforeMethodParamateres[] = $this->setProcessParameters($beforeParameters[$k], $decodeData, array());
                        } else {
                            if (array_key_exists($k, $decodeData)) {
                                $beforeMethodParamateres[] = $decodeData[$k];
                            } else {
                                $beforeMethodParamateres[] = $beforeParameters[$k];
                            }
                        }
                    }
                }
                try {
                    $result = call_user_func_array(array($beforeServiceManager, $value['name']), $beforeMethodParamateres);
                } catch (\Exception $e) {
                    return $this->setStatusData($document, 'Error', $e->getMessage().' Error in before action method execution...');
                }
            }
        }
        return $result;
    }

    public function setProjectSettings($data, $action){
        if($action == "set"){
            //$this->sessionManager->set('project_settings_web', $this->projectSetting);
            $this->projectSetting['user_id'] = $data['user_id'];
            $this->projectSetting['user_type'] = $data['user_type'];
            //isset($data['erp_id']) ? $this->sessionManager->set('quote_erp_id',$data['erp_id']) : "";
            $this->projectSetting['instance_id'] = $data['instance_id'];
            $this->projectSetting['instance_type'] = $data['instance_type'];
            #$this->projectSetting['culture_id'] = $data['culture_id'];
            $this->projectSetting['culture_code'] = isset($data['culture_code']) ? $data['culture_code'] : $data['culture'];
        }else{
            //$this->projectSetting = $this->sessionManager->get('project_settings_web');
        }
    } 
    
    public function setRequestParameter($data){
        foreach ($data as $key => $value) {
            if(is_object($value) || is_array($value)) {
                $value = (array) json_decode(json_encode($value), true);
            }
            $this->request->request->set($key, $value);
        }
    }
    
    public function setSessionParameters($data)
    {
        foreach ($data as $key => $value) {
            if(is_object($value)) {
                $value = (array) json_decode(json_encode($value), true);
            }
            $this->sessionManager->set($key, $value);
        }
    }
}