<?php

require_once ('lib-mbapi/include/modules/registrar/registrar.php');
require_once ('lib-mbapi/include/modules/registrar/core/rucenter/RuCenterModule.php');

// Specific Rucenter Exceptions
class RucenterModuleError extends Exception {}

/* Registrar class */

$className = 'RuCenter';
$GLOBALS['moduleInfo'][$className] = array(
    'type'          =>      'registrar',
    'status'        =>      Registrar::STATUS_STABLE,
    'version'       =>      '1.0.0',
    'displayName'   =>      'RuCenter',
    'author'        =>      'Parallels',
	'file'			=>		__FILE__,
	'countryCodes' => array('RU'),
);


class RuCenter extends Registrar
{
	const RUCENTER_ORG_TYPE = 'ORG';
	const RUCENTER_BUSINESS_PERSON_TYPE = 'PRS';
	const RUCENTER_INDIVIDUAL_TYPE = 'PRS';

    public function getModuleInfo() {
        return $GLOBALS['moduleInfo']['RuCenter'];
    }

    public function __construct($input) {

	    // quick fix to enable IDN support across all functions
	    if (isset($this->input['domainSLD']) && trim($this->input['domainSLD']) != '') {
	        $this->input['domainSLD'] = $this->getPUNYCode($this->input['domainSLD']);
	    }

		$this->capabilities[REGISTRAR_REGISTERDOMAIN] = 1;
		$this->capabilities[REGISTRAR_TRANSFERDOMAIN] = 0;
		$this->capabilities[REGISTRAR_RENEWDOMAIN] = 0;
		$this->capabilities[REGISTRAR_GETDOMAINEXTENDEDINFO] = 1;
		$this->capabilities[REGISTRAR_CHECKDOMAINAVAILABILITY] = 0;
		$this->capabilities[REGISTRAR_CHECKDOMAINTRANSFERAVAILABILITY] = 0;

		//Domain Management options
		$this->capabilities[REGISTRAR_GETDOMAINCONTACTDATA] = 1;
		$this->capabilities[REGISTRAR_SETDOMAINCONTACTDATA] = 0;
		$this->capabilities[REGISTRAR_GETDOMAINRENEWTYPEOPTIONS] = 0;
		$this->capabilities[REGISTRAR_SETDOMAINRENEWTYPEOPTIONS] = 0;
		$this->capabilities[REGISTRAR_GETDOMAINREGISTRARLOCKOPTIONS] = 0;
		$this->capabilities[REGISTRAR_SETDOMAINREGISTRARLOCKOPTIONS] = 0;
		$this->capabilities[REGISTRAR_GETDOMAINACCESSPASSWORD] = 0;
		$this->capabilities[REGISTRAR_SETDOMAINACCESSPASSWORD] = 0;
		$this->capabilities[REGISTRAR_GETDOMAINDNS] = 1;
		$this->capabilities[REGISTRAR_SETDOMAINDNS] = 1;
		$this->capabilities[REGISTRAR_GETDOMAINRENEWDATE] = 0;
		$this->capabilities[REGISTRAR_LIVERENEW] = 0;

		$this->capabilities[REGISTRAR_CHECKACCOUNTBALANCE] = 0;
		$this->capabilities[REGISTRAR_GETTLDPRICING] = 0;
		$this->capabilities[REGISTRAR_GETTRANSFERSTATUS] = 0;
		$this->capabilities[REGISTRAR_GETTLDLIST] = 0;
		$this->capabilities[REGISTRAR_TLDS] = array_merge($this->contractOnlyTlds, $this->contactRequiredTlds);
		parent::Registrar($input);
		$this->capabilities[REGISTRAR_UPLOADDOCUMENTS] = 1;

     }

    // this function sends the call to register a new domain
    public function registerDomain()
    {
    	// initialize the arrayData variable
        $this->arrayData = array();
        try {

        	if (isset($this->input["domain_orderID"]) && "" != $this->input["domain_orderID"]) {
				$orderInfoRequest = $this->getOrderInfoRequest($this->input);
			    $orderInfoResponse = $this->makeTheCall($orderInfoRequest);
			    require_once("objects/Package.php");
			    switch ($orderInfoResponse->getBody()->getSection('order')->getParameter("state")->getValue()) {
			    	case self::ACTION_STATUS_COMPLETED :
			    		$this->commandStatus = self::ACTION_STATUS_COMPLETED;
			    		$this->arrayData["state"] = $orderResponse->getBody()->getSection("order")->getParameter("state")->getValue();
			    		break;
			    	case self::ACTION_STATUS_WAITING :
			    		$this->commandStatus = self::ACTION_STATUS_WAITING;
			    		$this->arrayData["PackageStatus"] = Package::STATUS_WORKINPROGRESS;
			    		break;
			    	default:
			    		$this->arrayData["PackageStatus"] = Package::STATUS_WORKINPROGRESS;
			    }
			    $this->setFlagsAndXML(1);
			    return;
        	}

			if (!isset($this->input["domain_subjectContract"])) {
				require_once("lib-tk/include/crypt/crypt.php");
				require_once("object_managers/CryptManager.php");
				if (!isset($this->input["domain_Password"])) {
					$this->arrayData["Password"] = $this->input["domain_Password"] = CryptManager::encrypt(getRandomPassword(16));
				}
				if (!isset($this->input["domain_TechPassword"])) {
					$this->arrayData["TechPassword"] = $this->input["domain_TechPassword"] = CryptManager::encrypt(getRandomPassword(16));
				}
				$contractRequest = $this->getNewContractRequest($this->input);
			    $contractResponse = $this->makeTheCall($contractRequest);
			    $this->arrayData["subjectContract"] = $this->input["domain_subjectContract"] = $contractResponse->getBody()->getParameter("login")->getValue();
			}

			if (!in_array($this->input['domainTLD'], $this->contractOnlyTlds) && !isset($this->input["domain_nicHdl"])) {
				$contactRequest = $this->getNewContactRequest($this->input);
				$contactResponse = $this->makeTheCall($contactRequest);
				$this->arrayData["nicHdl"] = $this->input["domain_nicHdl"] = $contactResponse->getBody()->getSection('contact')->getParameter("nic-hdl")->getValue();
			}

			$orderRequest = $this->getNewOrderRequest($this->input);
			$orderResponse = $this->makeTheCall($orderRequest);

			$this->arrayData["orderID"] = $orderResponse->getBody()->getSection("order")->getParameter("order_id")->getValue();
			$this->commandStatus = self::ACTION_STATUS_WAITING;
			$this->arrayData["PackageStatus"] = Package::STATUS_WORKINPROGRESS;
			$this->setFlagsAndXML(1);

        } catch (RucenterModuleError $e) {
			$this->addError(blmsg("TRANS_REGISTRARERROR"), $e->getMessage());
			$this->commandStatus = self::ACTION_STATUS_ERROR;
			$this->setFlagsAndXML(0);
        }

    }

    public function getAllDomainContractParams()
    {
    	$nonRequiredParams = $this->_getNonRequiredCommonParams();
    	return array_merge(
    		$nonRequiredParams,
    		$this->getRequiredCommonContractParams(),
    		$this->getRequiredOrganizationContractParams(),
    		$this->getRequiredEnterpreneurContractParams()
    	);
    }

    private function _getNonRequiredCommonParams()
    {
        return array(
    		"domain_subjectContract", "domain_Descr", "domain_ContractType", "domain_Password",
			"domain_OwnerFaxNo", "domain_OwnerMntNfy", "domain_OwnerDestAddr", "domain_TechPassword",
    	);
    }

    public function getRequiredCommonContractParams()
    {
    	return array(
    		"domain_OwnerEmail", "domain_OwnerCountryID",
    		"domain_OwnerPhone", "domain_OwnerPostAddr",
    		"domain_OwnerCurrencyID",
    	);
    }

    public function getRequiredIndividualContractParams()
    {
    	$unique = array(
    		"domain_OwnerPerson", "domain_OwnerPersonRus",
    		"domain_OwnerPassport", "domain_OwnerBirthdate",
    	);
    	return array_merge( $this->getRequiredCommonContractParams(), $unique );
    }

    public function getRequiredOrganizationContractParams()
    {
    	$unique = array(
    		"domain_OwnerOrgName", "domain_OwnerOrgRusName",
    		"domain_OwnerCode", "domain_OwnerKpp", "domain_OwnerAddressRus",
    	);
    	return array_merge( $this->getRequiredCommonContractParams(), $unique );
    }

    public function getRequiredEnterpreneurContractParams()
    {
    	return array_merge($this->getRequiredIndividualContractParams(), array('domain_OwnerCode'));
    }


	public function hideContactForm($tld)
	{
		if (!in_array($tld, $this->contractOnlyTlds)) {
			return 0;
		}
		return 1;
	}

	public function isDone()
	{
		if (self::ACTION_STATUS_WAITING == $this->commandStatus) {
			return false;
		}
		return true;
	}

	public function getDomainDNS(PackageDomain $domain) {
		$crypt = new Crypt(getPasswordHash(Crypt::ENCRYPTION_KEY));
		$action = new RuCenterEditDNSAction();
		$action->_mode = RuCenterEditDNSAction::MODE_DISPLAY;
		$action->_login = $this->getParameter("moduleUsername");
		$action->_password = $crypt->decrypt($this->getParameter("modulePassword"));
		$action->_subjectContract = $domain->getPackage()->getAttribute("domain_subjectContract");
		$action->_domain = $domain->domain_sld . "." . $domain->domain_tld;
		$action->_tld = $domain->domain_tld;
		RuCenterModule::setLang(BillingLocale::getLocale());
		$action->run();
		if (!is_null($action->errors)) {
			throw new ProductException(ProductException::E_FAIL_OPERATION, implode("\n", $action->errors));
		}
		return $action->getProperty("nameServers");
	}

	public function setDomainDNS(PackageDomain $domain) {
		$crypt = new Crypt(getPasswordHash(Crypt::ENCRYPTION_KEY));
		$action = new RuCenterEditDNSAction();
		$action->_mode = RuCenterEditDNSAction::MODE_PROCESS;
		$action->_login = $this->getParameter("moduleUsername");
		$action->_password = $crypt->decrypt($this->getParameter("modulePassword"));
		$action->_subjectContract = $domain->getPackage()->getAttribute("domain_subjectContract");
		$action->_domain = $domain->domain_sld . "." . $domain->domain_tld;
		$action->_tld = $domain->domain_tld;
		$action->nameServers = isset($_REQUEST["domainDNS"]) ? $_REQUEST["domainDNS"] : array();
		RuCenterModule::setLang(BillingLocale::getLocale());
		$action->run();
		if (!is_null($action->errors)) {
			throw new ProductException(ProductException::E_FAIL_OPERATION, implode("\n", $action->errors));
		}
		return;
	}

	public function uploadIdentityDocument(PackageDomain $domain, $identityDocumentFiledName) {
		$crypt = new Crypt(getPasswordHash(Crypt::ENCRYPTION_KEY));
		$action = new RuCenterUploadIdentityDocumentAction();
		$action->_login = $this->getParameter("moduleUsername");
		$action->_password = $crypt->decrypt($this->getParameter("modulePassword"));
		$action->_subjectContract = $domain->getPackage()->getAttribute("domain_subjectContract");
		$action->_domain = $domain->domain_sld . "." . $domain->domain_tld;
		$action->_identity_document_field_name = $identityDocumentFiledName;
		$action->run();
		if (!is_null($action->errors)) {
			throw new ProductException(ProductException::E_FAIL_OPERATION, implode("\n", $action->errors));
		}
		return;
	}

	public function getRegistrantParams($action, $domain_sld, $domain_tld, ClientContact $contact = NULL, $withTLDParams = false)
	{
		$registrantParams = array();
		if (in_array($domain_tld, $this->contactRequiredTlds)) {
			$registrantParams = parent::getRegistrantParams($action, $domain_sld, $domain_tld, $contact, $withTLDParams);
		}
		$client_id = is_null($contact) ? NULL : $contact->client_id;
        $packageWithContact =  is_null($client_id) ? NULL : $this->getPriorSubscription($this->input["configGroupID"], $client_id);
		$tld_params = $this->convertTLDParamsToFormDescriptor($this->getTLDParamsData($domain_tld), $client_id, "{$domain_sld}_");

        $visibleParams = $this->_getVisibleParams(bgpc($domain_sld."_domain_ContractType"));

        if (!is_null($tld_params)) {
			foreach ($tld_params as $panel) {
                foreach ($panel["inputs"] as &$input) {
                    $name = $this->replaceParamName($domain_sld, $input["id"]);
                    if (!in_array($name, $visibleParams)) {
                        $input["hidden"] = 1;
                    }

                    $input["read_only"] = !is_null($packageWithContact) ? 1 : 0 ;
                }
				$registrantParams[] = $panel;
			}
		}

		return $registrantParams;
	}

    private function _getVisibleParams($customerType)
    {
        return array_merge($this->getRequiredParams($customerType), $this->_getNonRequiredCommonParams());
    }

	public function collectRegistrantParams($action, $domain_sld, $domain_tld, ClientContact $contact = NULL)
	{
		$collectedParams = parent::collectRegistrantParams($action, $domain_sld, $domain_tld, $contact);
        $packageWithContact = !is_null($contact) ? $this->getPriorSubscription($this->input["configGroupID"], $contact->client_id) : null ;
        if (!is_null($packageWithContact)) {
            $productVariant = Factory()->ProductVariant($packageWithContact->product_variant_id);
            $registrar = Factory()->BillingRegistrar(array($productVariant->TLD->registrar_id, $productVariant->TLD->vendor_id));
            $domainAttrs = DataObject::getMapOf($packageWithContact->PackageAttributes, "package_attribute_name", "package_attribute_value");
            foreach($registrar->getModule()->getAllDomainContractParams() as $contractParam) {
                if (isset($collectedParams["data"][$contractParam])) {
                    continue;
                }

                $collectedParams["data"][$contractParam] = $domainAttrs[$contractParam];
            }
            $collectedParams["data"]["domain_HasContract"] = 1;
        }
        unset($collectedParams['errors_list']);

        $requiredParams = $this->getRequiredParams(bgpc($domain_sld."_domain_ContractType"));
        foreach ($collectedParams["form_descriptor"] as &$params) {
            foreach ($params["inputs"] as &$input) {
                $name = $this->replaceParamName($domain_sld, $input["id"]);
                if (!in_array($name , $requiredParams) && !in_array($name , $this->_getNonRequiredCommonParams())) {
                    $input["hidden"] = 1;
                    continue;
                }
                if ( is_null($input["default"]) && isset($collectedParams["data"][$name])) {
                    $input["default"] = $collectedParams["data"][$name];
                }
                if (1 == $input["required"] && ( !isset($collectedParams["data"][$name]) || "" == $collectedParams["data"][$name])) {
					$input["error_msg"] = $collectedParams["errors_list"][$input["id"]] = blmsg("TRANS_INVALID_FIELD_MESSAGE", array("FIELD_NAME" => blmsg($input["title"])));
                }
                if (!empty($input["validators"])) {
                    foreach ($input["validators"] as $validator => $expression) {
                        switch ($validator) {
                            case 'phone':
                                if (empty($input["error_msg"]) && !RuCenterChecker::phone($collectedParams["data"][$name])) {
                                    $input["error_msg"] = $collectedParams["errors_list"][$input["id"]] = blmsg("TRANS_INVALID_FIELD_MESSAGE", array("FIELD_NAME" => blmsg($input["title"])));
                                }
                                break;
                            case 'email':
                                if (empty($input["error_msg"]) && !RuCenterChecker::emailAddress($collectedParams["data"][$name])) {
                                    $input["error_msg"] = $collectedParams["errors_list"][$input["id"]] = blmsg("TRANS_INVALID_FIELD_MESSAGE", array("FIELD_NAME" => blmsg($input["title"])));
                                }
                                break;
                            case 'pattern':
                                if (empty($input["error_msg"]) && !RuCenterChecker::checkRegexp($expression, $collectedParams["data"][$name]) &&  "" != $collectedParams["data"][$name]) {
                                    $input["error_msg"] = $collectedParams["errors_list"][$input["id"]] = blmsg("TRANS_INVALID_FIELD_MESSAGE", array("FIELD_NAME" => blmsg($input["title"])));
                                }
                                break;
                            case 'maxDate':
                                if (empty($input["error_msg"]) && !RuCenterChecker::checkMaxDate($expression, $collectedParams["data"][$name])) {
                                    $input["error_msg"] = $collectedParams["errors_list"][$input["id"]] = blmsg("TRANS_INVALID_MAX_DATE", array("DATE" => blmsg(date('d.m.Y', strtotime(RuCenterChecker::MINUS18YEARS)))));
                                }
                                break;
                            case 'maxLength':
                                if (empty($input["error_msg"]) && !RuCenterChecker::checkMaxLength($expression, $collectedParams["data"][$name])) {
                                    $input["error_msg"] = $collectedParams["errors_list"][$input["id"]] = blmsg("TRANS_INVALID_LENGTH", array("LENGTH" => blmsg($expression)));
                                }
                                break;
                        }
                    }
                }
            }
        }

		return $collectedParams;
	}


	protected function getPriorSubscription($registrar_id, $client_id)
	{
		require_once("object_managers/PackageManager.php");
		return PackageManager::getDomainPackageByParams($client_id, $registrar_id);
	}

	protected function getTLDParamsData($tld)
	{
		require_once("objects/Client.php");
		$countries = array();
        foreach (Factory()->CountryList() as $country) {
        	$temp["title"] = "TRANS_ISO_3166_".$country->countries_iso_2;
        	$temp["value"] = $country->countries_iso_2;
        	$countries[] = $temp;
        }
        $currencies = array();
        foreach (Factory()->CurrencyList() as $currency) {
        	$temp["title"] = $currency->currency_name;
        	$temp["value"] = $currency->id;
        	$currencies[] = $temp;
        }
        $nonRequiredParams = array("domain_Descr", "domain_OwnerFaxNo", "domain_OwnerMntNfy", "domain_ContractType");
		return array(
			"title" => "TRANS_REGISTRAR_RUCENTER_CONTRACT_DATA",
			"additionalMessage" => "TRANS_REGISTRAR_RUCENTER_REGISTRATION_ADDITIONAL_INFO",
			"attributes" => array(
				array(
					"name" => "domain_ContractType",
                    "required" => true,
					"description" => "TRANS_REGISTRAR_RUCENTER_CLIENT_TYPE",
					"validationRequiredParams" => true,
					"allDomainParams" => $this->getAllDomainContractParams(),
					"defaultValue" => Client::TYPE_INDIVIDUAL_PERSON,
					"options" => array(
						array(
							"title" => "TRANS_REGISTRAR_RUCENTER_INDIVIDUAL_PERSON",
							"value" => Client::TYPE_INDIVIDUAL_PERSON,
							"paramsToShow" => array_merge($this->getRequiredIndividualContractParams(),$nonRequiredParams),
						),
						array(
							"title" => "TRANS_REGISTRAR_RUCENTER_COMMERCIAL_COMPANY",
							"value" => Client::TYPE_COMMERCIAL_COMPANY,
							"paramsToShow" => array_merge($this->getRequiredOrganizationContractParams(),$nonRequiredParams, array('domain_OwnerDestAddr')),
						),
						array(
							"title" => "TRANS_REGISTRAR_RUCENTER_INDIVIDUAL_ENTERPRENEUR",
							"value" => Client::TYPE_INDIVIDUAL_ENTERPRENEUR,
							"paramsToShow" => array_merge($this->getRequiredEnterpreneurContractParams(),$nonRequiredParams),
						),
					),
				),
				array(
					"name" => "domain_OwnerPerson",
                    "required" => true,
                    "validators" => array('pattern' => RuCenterChecker::P_ENGLISH_CHARACTERS),
					"description" => "TRANS_REGISTRAR_RUCENTER_CLIENT_ENG",
					"userdefined" => "True",
				),
				array(
					"name" => "domain_OwnerPersonRus",
                    "required" => true,
					"description" => "TRANS_REGISTRAR_RUCENTER_CLIENT_RUS",
					"userdefined" => "True",
				),
				array(
					"name" => "domain_OwnerPassport",
                    "required" => true,
                    "validators" => array('pattern' => RuCenterChecker::P_TWO_WORDS, 'maxLength' => 256),
					"description" => "TRANS_REGISTRAR_RUCENTER_PASSPORT",
					"hint" => "TRANS_REGISTRAR_RUCENTER_PASSPORT_HINT",
					"userdefined" => "True",
					"multiline" => "True",
				),
				array(
					"name" => "domain_OwnerBirthdate",
                    "required" => true,
                    "validators" => array('pattern' => RuCenterChecker::P_DATE_DDMMYYYY, 'maxDate' => strtotime(RuCenterChecker::MINUS18YEARS)),
					"userdefined" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_CLIENT_BIRTHDAY",
				),
				array(
					"name" => "domain_OwnerOrgName",
                    "required" => true,
                    "validators" => array('pattern' => RuCenterChecker::P_TWO_WORDS, 'maxLength' => 100),
					"userdefined" => "True",
					"multiline" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_COMMERCIAL_COMPANY_NAME",
				),
				array(
					"name" => "domain_OwnerOrgRusName",
                    "required" => true,
                    "validators" => array('pattern' => RuCenterChecker::P_TWO_WORDS, 'maxLength' => 256),
					"userdefined" => "True",
					"multiline" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_COMMERCIAL_COMPANY_RUSSIAN_NAME",
					"hint" => "TRANS_REGISTRAR_RUCENTER_COMMERCIAL_COMPANY_RUSSIAN_NAME_HINT",
				),
				array(
					"name" => "domain_OwnerCode",
                    "required" => true,
                    "validators" => array('pattern' => RuCenterChecker::P_DIGITS, 'maxLength' => 12),
					"userdefined" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_INN",
					"hint" => "TRANS_REGISTRAR_RUCENTER_INN_HINT",
				),
				array(
					"name" => "domain_OwnerKpp",
                    "required" => true,
                    "validators" => array('pattern' => RuCenterChecker::P_DIGITS, 'maxLength' => 9),
					"userdefined" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_KPP",
					"hint" => "TRANS_REGISTRAR_RUCENTER_KPP_HINT",
				),
				array(
					"name" => "domain_OwnerCountryID",
                    "required" => true,
					"description" => "TRANS_REGISTRAR_RUCENTER_COUNTRY",
					"default" => "RU",
					"options" => $countries,
				),
				array(
					"name" => "domain_OwnerCurrencyID",
                    "required" => true,
					"description" => "TRANS_REGISTRAR_RUCENTER_CURRENCY",
					"hint" => "TRANS_REGISTRAR_RUCENTER_CURRENCY_HINT",
					"default" => "RUB",
					"options" => $currencies,
				),
				array(
					"name" => "domain_OwnerAddressRus",
                    "required" => true,
                    "validators" => array('maxLength' => 256),
					"userdefined" => "True",
					"multiline" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_RUSSIAN_ADDRESS",
					"hint" => "TRANS_REGISTRAR_RUCENTER_RUSSIAN_ADDRESS_HINT",
				),
				array(
					"name" => "domain_OwnerPostAddr",
                    "required" => true,
                    "validators" => array('maxLength' => 256),
					"userdefined" => "True",
					"multiline" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_POST_RUSSIAN_ADDRESS",
					"hint" => "TRANS_REGISTRAR_RUCENTER_POST_RUSSIAN_ADDRESS_HINT",
				),
				array(
					"name" => "domain_OwnerDestAddr",
					"userdefined" => "True",
					"multiline" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_CONSIGNEE_RUSSIAN_ADDRESS",
					"hint" => "TRANS_REGISTRAR_RUCENTER_CONSIGNEE_RUSSIAN_ADDRESS_HINT",
				),
				array(
					"name" => "domain_OwnerPhone",
                    "required" => true,
                    "validators" => array('phone' => null),
					"userdefined" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_PHONE",
					"hint" => "TRANS_REGISTRAR_RUCENTER_PHONE_HINT",
				),
				array(
					"name" => "domain_OwnerFaxNo",
					"userdefined" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_FAX",
					"hint" => "TRANS_REGISTRAR_RUCENTER_FAX_HINT",
				),
				array(
					"name" => "domain_OwnerEmail",
                    "required" => true,
                    "validators" => array('email' => null),
					"userdefined" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_EMAIL",
				),
				array(
					"name" => "domain_OwnerMntNfy",
					"userdefined" => "True",
					"description" => "TRANS_REGISTRAR_RUCENTER_MNT_NFY",
					"hint" => "TRANS_REGISTRAR_RUCENTER_MNT_NFY_HINT",
				),
				array(
					"name" => "domain_Descr",
					"userdefined" => "True",
					"multiline" => "True",
                    "validators" => array('pattern' => RuCenterChecker::P_ENGLISH_CHARACTERS, 'maxLength' => 300),
					"description" => "TRANS_REGISTRAR_RUCENTER_DOMAIN_DESCR",
                    "hint" => "TRANS_REGISTRAR_RUCENTER_DOMAIN_DESCR_HINT",
				),
			),
		);
	}

	protected function registrarFormatPhone() {}

	protected function getDefaultConfigOptions()
	{
    	return array(
    		"TRANS_REGISTRAR_MODULE_SETTINGS" => array(
    			array('moduleUsername', "t", 1, NULL, "TRANS_REGISTRAR_RUCENTER_USERNAME", NULL, NULL),
    			array('modulePassword', "p", 1, NULL, "TRANS_REGISTRAR_RUCENTER_PASSWORD", NULL, NULL),
    			array('moduleUseCustomNameserver', "b", 0, false, "TRANS_REGISTRAR_RUCENTER_USE_CUSTOM_NAMESERVER", NULL, NULL),
    			array('moduleAllowChangeDNS', "b", 0, false, "TRANS_REGISTRAR_RUCENTER_ALLOW_CHANGE_DNS", NULL, NULL),
    			array('moduleAllowUploadDocuments', "b", 0, true, "TRANS_REGISTRAR_RUCENTER_ALLOW_UPLOAD_DOCUMENTS", NULL, NULL)
    		),
    		"TRANS_REGISTRAR_NS" => array(
    			array("domainNameserver1", "t", 0, NULL, "TRANS_REGISTRAR_NS1", NULL, NULL),
				array("domainNameserver2", "t", 0, NULL, "TRANS_REGISTRAR_NS2", NULL, NULL),
				array("domainNameserver3", "t", 0, NULL, "TRANS_REGISTRAR_NS3", NULL, NULL),
				array("domainNameserver4", "t", 0, NULL, "TRANS_REGISTRAR_NS4", NULL, NULL),
    		)
    	);
    }

    private function getRequestID()
    {
    	return date("YmdHis").mt_rand();
    }

    private function getHeader($request, $operation, $input)
    {
    	$header = new RuCenterMessageHeader();
    	$header->login = $this->UID;
    	$header->password = $this->PW;
    	$header->lang = 'en';
    	$header->request = $request;
    	$header->operation = $operation;
    	$header->request_id = $this->getRequestID();

    	$requestWithoutLogin = array(
    		array("contract", "create"),
    		array("order", "get"),
    	);

		if (!in_array( array($request, $operation), $requestWithoutLogin ) ) {
			$header->subject_contract = $input["domain_subjectContract"];
		}
		return $header;
    }

    private function getNewContractRequest(array $input)
    {
    	$header = $this->getHeader("contract", "create", $input);
		$body = new RuCenterMessageBody();
		$section = $body->addSection(new RuCenterMessageSection("contract"));
		require_once("object_managers/CryptManager.php");
		$section->password = CryptManager::decrypt($input['domain_Password']);
		$section->tech_password =  CryptManager::decrypt($input['domain_TechPassword']);
		$addressPost = $this->getMultilineParameter($input['domain_OwnerPostAddr'], 'p-addr');

        $section->addParameter($addressPost);
		$section->phone = $input['domain_OwnerPhone'];
		$section->currency_id = str_replace("RUB", "RUR", $input['domain_OwnerCurrencyID']);
		$section->country = $input['domain_OwnerCountryID'];
		$section->fax_no = $input['domain_OwnerFaxNo'];
		$section->e_mail = $input['domain_OwnerEmail'];
		$section->mnt_nfy = $input['domain_OwnerMntNfy'];

		require_once("objects/Client.php");
		switch ($input['domain_ContractType']) {
			case Client::TYPE_INDIVIDUAL_PERSON :
				$section->contract_type = self::RUCENTER_INDIVIDUAL_TYPE;
				$this->getIndividualTypeContractData($section, $input);
				break;
			case Client::TYPE_INDIVIDUAL_ENTERPRENEUR :
				$section->contract_type = self::RUCENTER_BUSINESS_PERSON_TYPE;
				$this->getBusinessPersonTypeContractData($section, $input);
				break;
			case Client::TYPE_COMMERCIAL_COMPANY :
				$section->contract_type = self::RUCENTER_ORG_TYPE;
				$this->getOrgTypeContractData($section, $input);
				break;
		}

		return new RuCenterRequest($header,$body);
    }

    private function getIndividualTypeContractData(RuCenterMessageSection $section, array $input)
    {
		$section->person = $input['domain_OwnerPerson'];
        $passport = $this->getMultilineParameter($input['domain_OwnerPassport'], 'passport');
        $section->addParameter($passport);
		$section->person_r = $input['domain_OwnerPersonRus'];
		$section->birth_date = $input['domain_OwnerBirthdate'];
    }

    private function getBusinessPersonTypeContractData(RuCenterMessageSection $section, array $input)
    {
    	$section->person = $input['domain_OwnerPerson'];
		$section->person_r = $input['domain_OwnerPersonRus'];
		$passport = $this->getMultilineParameter($input['domain_OwnerPassport'], 'passport');
        $section->addParameter($passport);
		$section->birth_date = $input['domain_OwnerBirthdate'];
		$section->code = $input['domain_OwnerCode'];
		$addressDest = $this->getMultilineParameter($input['domain_OwnerDestAddr'], 'd-addr');
        $section->addParameter($addressDest);
    }

    private function getOrgTypeContractData(RuCenterMessageSection $section, array $input)
    {
    	$orgName = $this->getMultilineParameter($input['domain_OwnerOrgName'], 'org');
        $section->addParameter($orgName);
        $orgRusName = $this->getMultilineParameter($input['domain_OwnerOrgRusName'], 'org-r');
        $section->addParameter($orgRusName);
		$section->code = $input['domain_OwnerCode'];
		$section->kpp = $input['domain_OwnerKpp'];
        $addressRus = $this->getMultilineParameter($input['domain_OwnerAddressRus'], 'address-r');
        $section->addParameter($addressRus);
        $addressDest = $this->getMultilineParameter($input['domain_OwnerDestAddr'], 'd-addr');
        $section->addParameter($addressDest);
    }

    private function getMultilineParameter($inputParameterValue, $requestParameterName)
    {
    	$inputParameter = explode(RuCenterMessage::LF, str_replace(RuCenterMessage::CRLF, RuCenterMessage::LF, $inputParameterValue));
		$parameter = new RuCenterMessageParameter($requestParameterName);
        foreach ($inputParameter as $str) {
			$parameter->addValue($str);
        }
        return $parameter;
    }

    private function getNewOrderRequest(array $input)
    {
		$header = $this->getHeader("order", "create", $input);
		$body = new RuCenterMessageBody();
		$section = $body->addSection(new RuCenterMessageSection("order-item"));
		$section->action = 'new';
		$section->descr = $input['domain_Descr'];
        if ( $this->config['moduleUseCustomNameserver'] ) {
            $configNameservers = array(
                'domainNameserver1',
                'domainNameserver2',
                'domainNameserver3',
                'domainnameserver4'
            );
            $nServer = new RuCenterMessageParameter("nserver");
            foreach ($configNameservers as $nameServer) {
				$nServer->addValue($this->config[$nameServer]);
            }
            $section->addParameter($nServer);
        }
		$section->nserver = $input['domain_Nserver'];
		$domain = "{$input['domainSLD']}.{$input['domainTLD']}";

		if (!in_array($input['domainTLD'], $this->contractOnlyTlds)) {
        	$section->template = 'client_rrp';
			$section->period = $input['domainYears'];
			$section->domain = $domain;
			$section->admin_c = $section->bill_c = $section->tech_c = $input['domain_nicHdl'];
		}

        $this->fillSectionService($section, $input);
		return new RuCenterRequest($header,$body);
    }

    private function fillSectionService($section, $input)
    {
        $domain = "{$input['domainSLD']}.{$input['domainTLD']}";
        switch ($input['domainTLD']) {
			case "ru":
				$section->service = 'domain_ru';
				$section->template = 'client_ru';
				$section->domain = $domain;
				break;
			case "su":
				$section->service = 'domain_su';
				$section->template = 'client_ru';
				$section->domain = $domain;
				break;
			case "рф":
				$section->service = 'domain_rf';
				$section->template = 'domain_rf';
				$section->domain = billing_idn2ascii("{$input['domainSLD']}.{$input['domainTLD']}");
				break;
			case "me":
				$section->service = 'domain_epp_me';
				break;
			case "lc":
				$section->service = 'domain_epp_lc';
				break;
			case "sc":
				$section->service = 'domain_epp_sc';
				break;
			case "vc":
				$section->service = 'domain_epp_vc';
				break;
			case "cc":
				$section->service = 'domain_epp_cc';
				break;
			case "tv":
				$section->service = 'domain_epp_tv';
				break;
			case "tel":
				$section->service = 'domain_epp_tel';
				break;
			case "mobi":
				$section->service = 'domain_epp_mobi';
				break;
			case "name":
				$section->service = 'domain_epp_name';
				break;
			case "travel":
				$section->service = 'domain_epp_travel';
				$section->uin = $input['domain_nicHdl'];
				break;
			case "aero":
				$section->service = 'domain_epp_aero';
				$section->authid = $section->authkey = $input['domain_nicHdl'];
				break;
			case "pro":
				$section->service = 'domain_epp_pro';
				break;
			case "ag":
				$section->service = 'domain_epp_ag';
				break;
			case "bz":
				$section->service = 'domain_epp_bz';
				break;
			case "hn":
				$section->service = 'domain_epp_hn';
				break;
			case "mn":
				$section->service = 'domain_epp_mn';
				break;
            case "tashkent.su":
            case "bukhara.su":
            case "grozny.su":
            case "jambyl.su":
            case "kurgan.su":
            case "lenug.su":
            case "obninsk.su":
            case "penza.su":
                $section->template = 'client_ru';
                $section->service = 'domain_'.str_replace(".", "_", $input['domainTLD']);
                $section->domain = $domain;
                break;
			default:
				$section->service = 'domain_rrp';
				break;
		}
        return $section;
    }

    private function getNewContactRequest(array $input)
    {
		$header = $this->getHeader("contact", "create", $input);
		$body = new RuCenterMessageBody();
		$section = $body->addSection(new RuCenterMessageSection("contact"));

		$section->status = (1 == $input['domain_HasContract']) ? 'contact' : 'registrant';
		$section->org = $input['registrantOrganizationName'];
		require_once("objects/Client.php");
		switch ($input['domain_ContractType']) {
			case Client::TYPE_INDIVIDUAL_PERSON :
			case Client::TYPE_INDIVIDUAL_ENTERPRENEUR :
				$section->name = "{$input['registrantLastName']} {$input['registrantFirstName']}";
				break;
			case Client::TYPE_COMMERCIAL_COMPANY :
				$section->name = $input['registrantOrganizationName'];
				break;
		}
		$section->country = $input['registrantCountry'];
		$section->region = $input['registrantState'];
		$section->city = $input['registrantCity'];
		$section->street = $input['registrantAddress1'];
		$section->zipcode = $input['registrantPostalCode'];
		$section->phone = $input['registrantPhone'];
		$section->fax = $input['registrantFax'];
		$section->email = $input['registrantEmail'];

		return new RuCenterRequest($header,$body);
    }

    private function getOrderInfoRequest(array $input)
    {
		$header = $this->getHeader("order", "get", $input);
		$body = new RuCenterMessageBody();
		$section = $body->addSection(new RuCenterMessageSection("order"));
		$orderID = new RuCenterMessageParameter("order_id");
		$orderID->addValue($input["domain_orderID"]);
		$section->addParameter($orderID);
		return new RuCenterRequest($header,$body);
    }

    // from any function that needs to make a cURL call, we will pass the
    // post values to this function, which will actually make the call
    private function makeTheCall(RuCenterRequest $request)
    {
		try {
			$data = $request->generate();
			if ("" == $data) {
				throw new Exception('Empty request to Rucenter.');
			}
			dbg("Request to Rucenter");
			dbg($data);

			$curl = curl_init();
			$data = mb_convert_encoding($data, "koi8-r", "utf8");
			curl_setopt($curl, CURLOPT_URL, $this->getURL());
			curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($curl, CURLOPT_POST, true);
			curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($curl, CURLOPT_POSTFIELDS, array('SimpleRequest' => $data));

			$attemptsCount = 0;
			while (!($output = curl_exec($curl)) && $attemptsCount < RuCenterModule::REQUEST_ATTEMPTS_COUNT) {
				$attemptsCount++;
			}

			$output = mb_convert_encoding($output, "utf8", "koi8-r");

			dbg("Response from Rucenter");
			dbg($output);
			dbg("CURL error if is:");
			dbg(curl_error($curl));

			$responce = RuCenterResponce::load($output);
			curl_close($curl);

			switch ($responce->getState()) {
				case 200:
					if ($request->getHeader()->getParameter("request-id")->getValue() != $responce->getHeader()->getParameter("request-id")->getValue()) {
						throw new RucenterModuleError("Invalid request-id in Rucenter response.");
					}
					break;
				default:
					throw new RucenterModuleError(implode("\n", $responce->getErrors()));
					break;
			}

		} catch (Exception $e) {
			throw new RucenterModuleError($e->getMessage());
		}

		return $responce;
    }

    private function getURL()
    {
        return 'https://www.nic.ru/dns/dealer';
    }

    private function setFlagsAndXML($hasExecutedSuccessfully = 0)
    {
	    $this->hasExecutedSuccessfully = $hasExecutedSuccessfully;
        $this->hasExecuted = 1;
        $this->xmlData = $this->getRegistrarReturnXML();
    }

    private function getRequiredParams($customerType = null)
    {
        require_once("objects/Client.php");
        if (null == $customerType) {
            $customerType = Client::TYPE_INDIVIDUAL_PERSON;
        }
        $requiredParams = array();
		switch ($customerType) {
            case Client::TYPE_INDIVIDUAL_PERSON:
                $requiredParams = $this->getRequiredIndividualContractParams();
                break;
            case Client::TYPE_COMMERCIAL_COMPANY:
                $requiredParams = $this->getRequiredOrganizationContractParams();
                break;
            case Client::TYPE_INDIVIDUAL_ENTERPRENEUR:
                $requiredParams = $this->getRequiredEnterpreneurContractParams();
                break;
        }
        return $requiredParams;
    }

    private function replaceParamName($domainSLD, $name)
    {
        return str_replace($domainSLD."_", "", $name);
    }

    private $contractOnlyTlds = array('рф', 'ru', 'su', 'bukhara.su', 'tashkent.su', 'bukhara.su',
        'grozny.su', 'jambyl.su', 'kurgan.su', 'lenug.su', 'obninsk.su', 'penza.su');
    private $contactRequiredTlds = array('com', 'net', 'org', 'biz', 'info', 'me', 'lc', 'sc', 'vc',
    	'cc', 'tv', 'tel', 'mobi', 'name', 'travel', 'aero', 'pro', 'ag', 'bz', 'hn', 'mn');
    private $commandStatus;
    private $header;
    private $contract;
    private $orderItem;
}
