<?php
if (!function_exists('hex2bin')) {
    function hex2bin($data)
    {
        static $old;
        if ($old === null) {
            $old = version_compare(PHP_VERSION, '5.2', '<');
        }
        $isobj = false;
        if (is_scalar($data) || (($isobj = is_object($data)) && method_exists($data, '__toString'))) {
            if ($isobj && $old) {
                ob_start();
                echo $data;
                $data = ob_get_clean();
            } else {
                $data = (string)$data;
            }
        } else {
            trigger_error(__FUNCTION__ . '() expects parameter 1 to be string, ' . gettype($data) . ' given', E_USER_WARNING);
            return;
        }
        $len = strlen($data);
        if ($len % 2) {
            trigger_error(__FUNCTION__ . '(): Hexadecimal input string must have an even length', E_USER_WARNING);
            return false;
        }
        if (strspn($data, '0123456789abcdefABCDEF') != $len) {
            trigger_error(__FUNCTION__ . '(): Input string must be hexadecimal string', E_USER_WARNING);
            return false;
        }
        return pack('H*', $data);
    }
}
require_once __DIR__ . '/../vendor/lib/autoload/sfCoreAutoload.class.php';
sfCoreAutoload::register();

class ProjectConfiguration extends sfProjectConfiguration
{
    public function setup()
    {
        $this->enablePlugins('sfDoctrinePlugin');
        $this->enablePlugins('sfImageTransformPlugin');
        $this->enablePlugins('sfCaptchaGDPlugin');
        $this->enablePlugins('doAuthPlugin');
        $this->enablePlugins('sfRUtilsPlugin');
        $this->enablePlugins('sfSphinxPlugin');
        $this->enablePlugins('csSettingsPlugin');
    }
    public function configureDoctrine(Doctrine_Manager $manager)
    {
        if(class_exists('customListener')){
            $manager->setAttribute(Doctrine_Core::ATTR_THROW_EXCEPTIONS, false);
        }
    }
    public function configureDoctrineConnection(Doctrine_Connection $connection)
    {
        $connection->exec("SET @@session.time_zone = '+03:00'");

        if(class_exists('customListener')){
            $connection->setEventListener(new customListener());
        }
    }
}

class ProjectUtils
{
    public static function getVersion()
    {
        $version_file = sfConfig::get('sf_data_dir') . '/version.txt';
        if (file_exists($version_file)) {
            $version_content = file_get_contents(sfConfig::get('sf_data_dir') . '/version.txt');
            $exp = explode("\n", $version_content);
            return $exp[0];
        }
        return '';
    }

    public static function uuidToHex($uuid)
    {
        return str_replace('-', '', $uuid);
    }

    public static function hexToUuid($hex)
    {
        $regex = '/^([\da-f]{8})([\da-f]{4})([\da-f]{4})([\da-f]{4})([\da-f]{12})$/';
        return preg_match($regex, $hex, $matches) ?
            "{$matches[1]}-{$matches[2]}-{$matches[3]}-{$matches[4]}-{$matches[5]}" :
            FALSE;
    }

    public static function hexToInteger($hex)
    {
        $bin = pack('h*', $hex);
        return unpack('L*', $bin);
    }

    public static function integerToHex($integers)
    {
        $args[0] = $integers;
        $args[1] = 'L*';
        @ksort($args);
        $bin = call_user_func_array('pack', $args);
        $results = unpack('h*', $bin);
        return $results[1];
    }

    public static function base64url_encode($data)
    {
        return exec("echo -n '" . $data . "' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =");
    }

    public static function nohup($file)
    {
        return exec('nohup ' . $file . ' > /dev/null 2>&1 &');
    }

    public static function nohup_task($task)
    {
        return ProjectUtils::nohup(sfConfig::get('sf_root_dir') . '/symfony ' . $task);
    }

    public static function get($url, $alwaysReturn = false, $headers = array())
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if (count($headers) > 0) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        $r = curl_exec($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        return $info['http_code'] === 200 || $alwaysReturn ? $r : null;
    }

    public static function post($url, $data, $alwaysReturn = false, $headers = array())
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if (count($headers) > 0) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        $r = curl_exec($ch);

        $info = curl_getinfo($ch);
        curl_close($ch);
        return $info['http_code'] === 200 || $alwaysReturn ? $r : null;
    }

    public static function pushPost($data)
    {
        if (strpos($data["notification"]["title"], "debugDEV1") !== false || strpos($data["notification"]["body"], "debugDEV1") !== false) {
            sfConfig::set('app_send_push', true);
        }

        if(!sfConfig::get('app_push_send')){
            return 'send push off';
        }

        if(!sfConfig::get('app_push_fb_key')){
            return 'fb_server_key not found';
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send');
        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type:application/json", "Authorization:key=" . sfConfig::get('app_push_fb_key')));
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $r = curl_exec($ch);
        curl_close($ch);
        return $r;
    }

    public static function wsPub($channel, $data)
    {
        if(sfConfig::has('app_ws_pub'))
        {
            self::post(sfConfig::get('app_ws_pub') . '?channel=' . $channel, json_encode($data));
        }
    }

    public static function generateUuid()
    {
        mt_srand((double)microtime() * 10000);
        $charid = strtolower(md5(uniqid(rand(), true)));
        $hyphen = chr(45);
        $uuid = substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12);
        return $uuid;
    }

    public static function arrayKeysFilter($items = array(), $key = 'id')
    {
        $ret = array();
        foreach ($items as $item) {
            $ret[] = $item[$key];
        }
        return $ret;
    }

    public static function cubeRecreate()
    {
        exec('nohup ' . sfConfig::get('sf_root_dir') . '/symfony cube:recreate > /dev/null 2>&1 &');
    }

    static function smsSend($phone, $mes)
    {
        if(sfConfig::get("app_sms_send") && sfConfig::get("app_sms_url") && sfConfig::get("app_sms_login") && sfConfig::get("app_sms_password") && !in_array($phone, sfConfig::get('app_sms_phone_deny'))){
            $data = array(
                'login' => sfConfig::get("app_sms_login"),
                'psw' => sfConfig::get("app_sms_password"),
                'phones' => $phone,
                'mes' => $mes
            );
            if(sfConfig::get("app_sms_sender")){
                $data['sender'] = sfConfig::get("app_sms_sender");
            }
            $log_path = sfConfig::get('sf_log_dir') . '/sms/' . date('m_Y') . '.log';
            LogUtils::logFile(print_r($data, true), $log_path);
            $res = ProjectUtils::post(sfConfig::get("app_sms_url"), $data);
            LogUtils::logFile($res, $log_path);
        }
    }

    static function getType($mime)
    {
        $types = array(
            'application/pdf' => 'pdf',
            'application/vnd.ms-excel' => 'xlsx',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xls',
            'application/msword' => 'docx',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'doc',
            'application/vnd.ms-powerpoint' => 'ppt',
            'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
            'image/png' => 'png',
            'image/jpeg' => 'jpg',
            'image/svg+xml' => 'svg',
            'audio/mpeg' => 'mp3',
            'video/mp4' => 'mp4',
            'video/mpeg' => 'mpeg',
            'video/webm' => 'webm'
        );
        return isset($types[$mime]) ? $types[$mime] : null;
    }

    static function ymActive()
    {
        return (sfConfig::get('app_ym_status') === 'on' || (sfConfig::get('app_ym_status') === 'test') && ProjectUtils::ymParams('shop') && ProjectUtils::ymParams('key'));
    }

    static function ymParams($param = false)
    {
        if(!in_array(sfConfig::get('app_ym_status'), array('test', 'on'))){
            return false;
        }
        if($param === 'shop'){
            return sfConfig::get(sfConfig::get('app_ym_status') === 'on' ? 'app_ym_shopId' : 'app_ym_testShopId');
        }else{
            return sfConfig::get(sfConfig::get('app_ym_status') === 'on' ? 'app_ym_key' : 'app_ym_testKey');
        }
    }

    static function rusDate($date, $format = 'd F Y')
    {
        $dt = sfRUtils::dt();
        $params = new TimeParams();
        $params->date = strtotime($date);
        $params->format = $format;
        $params->monthInflected = true;
        return $dt->ruStrFTime($params);
    }
}

class LogUtils
{
    static function time($start = true)
    {
        static $time_start = null;
        if($start){
            $time_start = microtime(true);
        }else{
            return round((microtime(true) - $time_start) * 1000) . ' ms';
        }
    }

    static function logFile($message, $filepath = null, $memory = true)
    {
        static $fix_filepath = null;

        $message = ' [' . date('Y-m-d H:i:s') . ']' . ($memory ? ' (' . number_format(memory_get_usage() / 1024, 2, ',', ' ') . ' КБ' . ')' : '') . "\n" . $message;

        if(!is_null($filepath)){
            $fix_filepath = $filepath;
        }
        if($fix_filepath){
            $dir = preg_replace('/(.*)\/.*$/', '$1', $fix_filepath);
            if(!file_exists($dir)){
                mkdir($dir, 0755, true);
            }
            file_put_contents($fix_filepath, $message . "\n", FILE_APPEND);
        }
    }
}

class Yavinesu
{
    public static function getVersion()
    {
        $request = sfContext::getInstance()->getRequest();
        $appversion = $request->getParameter('appversion', $request->getHttpHeader('appversion'));
        return $appversion === null || !is_numeric($appversion) ? 0 : (int)$appversion;
    }

    public static function getFullUrl()
    {
        $request = sfContext::getInstance()->getRequest();
        return 'http' . ($request->isSecure() ? 's' : '') . '://' . $request->getHost();
    }

    public static function getShortUrl($url)
    {
        return preg_replace("/^\/.{2}\/api\/" . "/iu", "", $url);
    }

    static function getImageInfo($image)
    {
        $path = sfConfig::get('sf_upload_dir') . '/f/' . $image;
        if(file_exists($path)){
            $size = getimagesize($path);
            if(is_array($size) && $size[0] > 0 && $size[1] > 0){
                $request = sfContext::getInstance()->getRequest();
                return array(
                    'url' => Yavinesu::getFullUrl($request) . '/u/f/' . $image,
                    'width' => $size[0],
                    'height' => $size[1]
                );
            }
        }
        return null;
    }

    public static function simpleTime($old_time, $lang = 'ru')
    {
        $time = time();
        $sec = $time - $old_time;
        if($sec < 60){
            if($lang === 'en'){
                return 'Freshly';
            }
            return 'Только что';
        }elseif($sec >= 60 && $sec < 120){
            if($lang === 'en'){
                return 'A minute ago';
            }
            return 'Минуту назад';
        }elseif($sec >= 86400 && $sec < 172800){
            if($lang === 'en'){
                return 'Yesterday';
            }
            return 'Вчера';
        }elseif($sec >= 172800 && $sec < 259200){
            if($lang === 'en'){
                return 'Two days ago';
            }
            return 'Позавчера';
        }
        $dt = sfRUtils::dt();
        if($sec >= 259200){
            if($lang === 'en'){
                return preg_replace("/, " . date('Y') . "/u", "", date('j F, Y'));
            }
            $params = new TimeParams();
            $params->date = $old_time;
            $params->format = 'd F, Y';
            $params->monthInflected = true;
            return preg_replace("/, " . date('Y') . "/u", "", $dt->ruStrFTime($params));
        }
        if($lang === 'en'){
            $old = DateTime::createFromFormat('U', $old_time);
            $now = new DateTime();
            $interval = $now->diff($old);
            return $interval->format($sec < 3600 ? '%i minute(s)' : '%h hour(s)') . ' ago';
        }else{
            return $dt->distanceOfTimeInWords($old_time, $time, $sec < 3600 ? 5 : 4);
        }
    }

    static function getErrorMessage($form)
    {
        $error = array();
        if($form->hasGlobalErrors()){
            foreach ($form->getGlobalErrors() as $name => $global_error){
                $error[] = $global_error->getMessage();
            }
        }
        foreach ($form as $name => $field){
            if($field->hasError()){
                $opts = $field->getWidget()->getOptions();
                $repeat = false;
                if(count($error) > 0){
                    foreach ($error as $key => $value){
                        if(trim(preg_replace('/^.*\:(.*)$/', '$1', $value)) === trim($field->getError())){
                            $error[$key] = preg_replace('/^(.*)\:.*$/', '$1', $value) . ', ' . ($opts['label'] ? $opts['label'] : $name) . ': ' . $field->getError();
                            $repeat = true;
                            break;
                        }
                    }
                }
                if(!$repeat){
                    $error[] = ($opts['label'] ? $opts['label'] : $name) .  ': ' . $field->getError();
                }
            }
        }
        return implode(";\n", $error);
    }

    static function getFormErrors($form)
    {
        $errors = array();
        foreach ($form as $name => $field) {
            if ($field->hasError()) {
                $errors[isset($form::$replace_names) && is_array($form::$replace_names) && isset($form::$replace_names[$name]) ? $form::$replace_names[$name] : $name] = (string)$field->getError();
            }
        }
        $global_errors = null;
        if($form->hasGlobalErrors()){
            $global_errors = array();
            foreach ($form->getGlobalErrors() as $globalError){
                $global_errors[] = (string)$globalError;
            }
            $global_errors = implode(";\n", $global_errors);
        }
        return array(
            'errors' => $errors,
            'global_errors' => $global_errors
        );
    }

    static function searchAddress($query = '')
    {
        $result = array(
            'state' => 'error',
            'code' => 'empty_query',
            'message' => 'Пустая поисковая строка',
        );
        if($query){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, 'https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/address');
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array(
                    'query' => $query,
                    'locations' => array('region' => 'москва'/*'city' => 'уфа'*/)))
            );
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Authorization: Token ' . sfConfig::get('app_dadata_key'),
                'Content-Type: application/json'));
            $r = curl_exec($ch);
            $info = curl_getinfo($ch);
            curl_close($ch);
            if($info['http_code'] === 200 && is_array($response = json_decode($r, true))){
                $result = array(
                    'state' => 'success',
                    'data' => array()
                );
                if(isset($response['suggestions']) && is_array($response['suggestions']) && count($response['suggestions']) > 0){
                    foreach ($response['suggestions'] as $suggestion){
                        $good_address = $suggestion['data']['house'] && $suggestion['data']['street_with_type'] && $suggestion['data']['geo_lat'] && $suggestion['data']['geo_lon'];
                        $result['data'][] = array(
                            'title' => $suggestion['value'],
                            'streetHome' => $suggestion['data']['street_with_type'] . ' ' . $suggestion['data']['house'],
                            'coords' => $good_address ? ($suggestion['data']['geo_lat'] . ',' . $suggestion['data']['geo_lon']) : null
                        );
                    }
                }
            }elseif($info['http_code'] === 403){
                $result['message'] = 'Техническая ошибка, попробуйте позднее';
            }
        }
        return $result;
    }

    static function priceFormat($price)
    {
        return str_replace('.00', '', number_format($price, 2, '.', ''));
    }

    static function weightFormat($weight)
    {
        return str_replace('.000', '', number_format($weight, 3, '.', ''));
    }

    static function getUnitpaySignature($account, $currency, $desc, $sum, $secretKey)
    {
        $hashStr = $account . '{up}' . $currency . '{up}' . $desc . '{up}' . $sum . '{up}' . $secretKey;
        return hash('sha256', $hashStr);
    }

    static function getCourierOutMin()
    {
        return csSettings::get('money_out_min') && is_numeric(csSettings::get('money_out_min')) && csSettings::get('money_out_min') > 0 ? (int)csSettings::get('money_out_min') : 1000;
    }
}

class base64ImageUtils
{
    public static function save($base64, $key)
    {
        $result = array('code' => 'Неправильный формат');
        if(!file_exists(sfConfig::get('sf_upload_dir') . '/f/')){
            mkdir(sfConfig::get('sf_upload_dir') . '/f/', 0755, true);
        }
        $filepath = sfConfig::get('sf_upload_dir') . '/f/' . ProjectUtils::generateUuid();
        if ($image_base = base64_decode($base64)) {
            if(file_put_contents($filepath, $image_base) !== false){
                $type = str_replace('image/', '', mime_content_type($filepath));
                if (in_array($type, array('jpeg', 'png')) && rename($filepath, $filepath . '.' . $type)) {
                    $filepath .= '.' . $type;
                    $upload_res = json_decode(Page::uploader($filepath, $key, 'path'), 'image');
                    if ($upload_res['state'] === 'success') {
                        $result['state'] = 'success';
                        $result['value'] = str_replace(sfConfig::get('sf_upload_dir') . '/f/', '', $upload_res['filename']);
                        unset($result['code']);
                    }else{
                        $result['code'] = $upload_res['errorTxt'];
                    }
                }
            }
        }
        return $result;
    }

    static function clean($images = array(), $size_key = false)
    {
        if(is_array($images) && count($images) > 0){
            if($size_key){
                $cfg_sizes = sfConfig::get('image_' . $size_key . '_sizes');
            }
            foreach ($images as $image_src) {
                if($image_src){
                    if($size_key && is_array($cfg_sizes) && count($cfg_sizes) > 0){
                        foreach ($cfg_sizes as $cfg_size_name => $cfg_size){
                            if($cfg_size_name !== 'min'){
                                self::remove(sfConfig::get('sf_upload_dir') . '/f/' . Page::replaceImageSize($image_src, $cfg_size_name));
                            }
                        }
                    }else{
                        self::remove(sfConfig::get('sf_upload_dir') . '/f/' . $image_src);
                    }
                }
            }
        }
    }

    static function remove($path)
    {
        if(file_exists($path)){
            @unlink($path);
        }
    }
}