<?php
if (!defined("ROOT_PATH"))
{
    header("HTTP/1.1 403 Forbidden");
    exit;
}
class pjBaseAppController extends pjController
{
    public $models = array();
    
    public $defaultFields = 'admin_fields';
    
    public $defaultFieldsIndex = 'admin_index';
    
    public $defaultLocale = 'admin_locale_id';
    
    public $defaultDir = 'admin_locale_dir';
    
    public $defaultLang = 'admin_locale_lang';
    
    public $loginAttempts = 'login_attempts';
    
    public $defaultLoginToken = 'admin_login_token';
    
    public $defaultLoginEmail = 'admin_login_email';
    
    public $defaultPermissions = 'admin_permissions';
        
    public function __construct()
    {
        $this->setLayout('pjActionAdmin');
    }
    
    public static function getConst($const)
    {
        $registry = pjRegistry::getInstance();
        $store = $registry->get('pjBase');
        return isset($store[$const]) ? $store[$const] : NULL;
    }
    
    public static function isPost()
    {
        if (($method = getenv('REQUEST_METHOD')) === false)
        {
            $method = @$_SERVER['REQUEST_METHOD'];
        }
        return $method == 'POST';
    }
    public static function isGet()
    {
        if (($method = getenv('REQUEST_METHOD')) === false)
        {
            $method = @$_SERVER['REQUEST_METHOD'];
        }
        return $method == 'GET';
    }
    
    protected function isInstaller()
    {
        $_get = pjRegistry::getInstance()->get('_get');
        if ($_get->toString('controller') == 'pjInstaller')
        {
            return true;
        }
        return false;
    }
    
    public function isEditor()
    {
    	return (int) $this->getRoleId() === 2;
    }
    
    protected function getDependencyManager($plugin='pjBase')
    {
        $baseDir = defined('PJ_INSTALL_PATH') ? PJ_INSTALL_PATH : NULL;
        
        $dm = new pjDependencyManager($baseDir, PJ_THIRD_PARTY_PATH);
        $dependencies = $baseDir . $this->getConstant($plugin, 'PLUGIN_CONFIG_PATH') . 'dependencies.php';
        if (is_file($dependencies))
        {
            $dm->load($dependencies)->resolve();
        }
        
        return $dm;
    }
    
    protected static function isIDsShown()
    {
        return isset($_SESSION['lang_show_id']) && (int) $_SESSION['lang_show_id'] === 1;
    }
    
    protected function sendForbidden()
    {
        header('HTTP/1.1 403 Forbidden');
        $this->setTemplate('pjBase', 'pjBase:elements/403');
    }

    protected function isAuthScreen()
    {
        return in_array($this->_get->toString('action'), array(
            'pjActionLogin',
            'pjActionForgot',
            'pjActionReset',
            'pjActionCaptcha',
            'pjActionCheckCaptcha',
            'pjActionCheckReCaptcha',
            'pjActionCheckLoginEmail',
            'pjActionResendPassword',
            'pjActionMessages',
        ), true);
    }
    
    protected function loadSetFields($force=FALSE, $locale_id=NULL, $fields=NULL)
    {
        if (is_null($locale_id))
        {
            $locale_id = $this->getLocaleId();
        }
        
        if (is_null($fields))
        {
            $fields = $this->defaultFields;
        }
        
        $registry = pjRegistry::getInstance();
        $field_arr = $this->session->getData($fields);
        if ($force
            || !$this->session->has($this->defaultFieldsIndex)
            || $this->session->getData($this->defaultFieldsIndex) != $this->option_arr['o_fields_index']
            || !$this->session->has($fields)
            || empty($field_arr))
        {
            pjAppController::setFields($locale_id);
            
            # Update session
            if ($registry->is('fields'))
            {
                $this->session->setData($fields, $registry->get('fields'));
            }
            $this->session->setData($this->defaultFieldsIndex, $this->option_arr['o_fields_index']);
        }
        
        if ($this->session->has($fields) && !empty($field_arr))
        {
            # Load fields from session
            $registry->set('fields', $this->session->getData($fields));
        }
        
        return TRUE;
    }
    
    protected function setLocalesData()
    {
        $locale_arr = pjLocaleModel::factory()
        ->select('t1.*, t2.file')
        ->join('pjBaseLocaleLanguage', 't2.iso=t1.language_iso', 'left')
        ->where('t2.file IS NOT NULL')
        ->orderBy('t1.sort ASC')->findAll()->getData();
        
        $lp_arr = array();
        foreach ($locale_arr as $item)
        {
            $lp_arr[$item['id']."_"] = $item['file'];
        }
        $this->set('lp_arr', $locale_arr);
        $this->set('locale_str', pjAppController::jsonEncode($lp_arr));
        $this->set('is_flag_ready', $this->requestAction(array('controller' => 'pjBaseLocale', 'action' => 'pjActionIsFlagReady'), array('return')));
    }
    
    public static function setFields($locale)
    {
        if(self::isIDsShown())
        {
            $fields = pjMultiLangModel::factory()
            ->select('CONCAT(t1.content, CONCAT(":", t2.id, ":")) AS content, t2.key')
            ->join('pjBaseField', "t2.id=t1.foreign_id", 'inner')
            ->where('t1.locale', $locale)
            ->where('t1.model', 'pjBaseField')
            ->where('t1.field', 'title')
            ->findAll()
            ->getDataPair('key', 'content');
        }else{
            $fields = pjMultiLangModel::factory()
            ->select('t1.content, t2.key')
            ->join('pjBaseField', "t2.id=t1.foreign_id", 'inner')
            ->where('t1.locale', $locale)
            ->where('t1.model', 'pjBaseField')
            ->where('t1.field', 'title')
            ->findAll()
            ->getDataPair('key', 'content');
        }
        $registry = pjRegistry::getInstance();
        $tmp = array();
        if ($registry->is('fields'))
        {
            $tmp = $registry->get('fields');
        }
        $arrays = array();
        foreach ($fields as $key => $value)
        {
            if (strpos($key, '_ARRAY_') !== false)
            {
                list($prefix, $suffix) = explode("_ARRAY_", $key);
                if (!isset($arrays[$prefix]))
                {
                    $arrays[$prefix] = array();
                }
                $arrays[$prefix][$suffix] = $value;
            }
        }
        require PJ_CONFIG_PATH . 'settings.inc.php';
        $fields = array_merge($tmp, $fields, $settings, $arrays);
        $registry->set('fields', $fields);
    }
    
    public static function jsonDecode($str)
    {
        if (function_exists('json_decode'))
        {
            return json_decode($str, true);
        }
        
        $Services_JSON = new pjServices_JSON(SERVICES_JSON_LOOSE_TYPE);
        return $Services_JSON->decode($str);
    }
    
    public static function jsonEncode($arr)
    {
        if (function_exists('json_encode'))
        {
            return json_encode($arr);
        }
        
        $Services_JSON = new pjServices_JSON();
        return $Services_JSON->encode($arr);
    }
    
    public static function jsonResponse($arr)
    {
        header("Content-Type: application/json; charset=utf-8");
        echo self::jsonEncode($arr);
        exit;
    }
    
    public static function friendlyURL($str, $divider='-')
    {
        $str = mb_strtolower($str, mb_detect_encoding($str)); // change everything to lowercase
        $str = trim($str); // trim leading and trailing spaces
        $str = preg_replace('/[_|\s]+/', $divider, $str); // change all spaces and underscores to a hyphen
        $str = preg_replace('/\x{00C5}/u', 'AA', $str);
        $str = preg_replace('/\x{00C6}/u', 'AE', $str);
        $str = preg_replace('/\x{00D8}/u', 'OE', $str);
        $str = preg_replace('/\x{00E5}/u', 'aa', $str);
        $str = preg_replace('/\x{00E6}/u', 'ae', $str);
        $str = preg_replace('/\x{00F8}/u', 'oe', $str);
        $str = preg_replace('/[^a-z\x{0400}-\x{04FF}0-9-]+/u', '', $str); // remove all non-cyrillic, non-numeric characters except the hyphen
        $str = preg_replace('/[-]+/', $divider, $str); // replace multiple instances of the hyphen with a single instance
        $str = preg_replace('/^-+|-+$/', '', $str); // trim leading and trailing hyphens
        return $str;
    }
    
    public function getLocaleId()
    {
        return $this->session->has($this->defaultLocale) && (int) $this->session->getData($this->defaultLocale) > 0 ? (int) $this->session->getData($this->defaultLocale) : false;
    }
    
    public function setLocaleId($locale_id)
    {
        $this->session->setData($this->defaultLocale, (int) $locale_id);
    }
    
    public function getLocaleDir()
    {
        return $this->session->has($this->defaultDir) && in_array($this->session->getData($this->defaultDir), array('ltr', 'rtl')) ? $this->session->getData($this->defaultDir) : 'ltr';
    }
    
    public function setLocaleDir($dir)
    {
        $this->session->setData($this->defaultDir, $dir);
    }
    
    public function getLocaleLang()
    {
        return $this->session->has($this->defaultLang) ? $this->session->getData($this->defaultLang) : NULL;
    }
    
    public function setLocaleLang($lang)
    {
        $this->session->setData($this->defaultLang, $lang);
    }
    
    public function getLocale()
    {
        return array(
            'locale_id' => $this->getLocaleId(),
            'dir' => $this->getLocaleDir(),
            'lang' => $this->getLocaleLang()
        );
    }
    
    public function setLocale($locale_id)
    {
        $this->setLocaleId($locale_id);
        
        $locale_arr = pjLocaleModel::factory()->find($locale_id)->getData();
        if (!empty($locale_arr))
        {
            $this->setLocaleDir($locale_arr['dir']);
            $this->setLocaleLang($locale_arr['language_iso']);
        }
    }
    
    public function getForeignId()
    {
        return 1;
    }
    
    public function beforeFilter()
    {
        $this->resetCss();
        $this->resetJs();
        
        $cssPath = $this->getConstant('pjBase', 'PLUGIN_CSS_PATH');
        $jsPath = $this->getConstant('pjBase', 'PLUGIN_JS_PATH');
        
        $dm = $this->getDependencyManager();
        
        $this->appendCss('css/bootstrap.min.css', $dm->getPath('bootstrap'), false, false);
        $this->appendCss('css/font-awesome.min.css', $dm->getPath('font_awesome'), false, false);
        $this->appendCss('toastr.min.css', $dm->getPath('toastr'), false, false);
        $this->appendCss('custom.css', $dm->getPath('icheck'), false, false);
        $this->appendCss('jquery.gritter.css', $dm->getPath('gritter'), false, false);
        $this->appendCss('sweetalert.css', $dm->getPath('sweetalert'), false, false);
        $this->appendCss('jquery.bootstrap-touchspin.min.css', $dm->getPath('touchspin'), false, false);
        $this->appendCss('animate.css', $cssPath);
        
        $this->appendJs('jquery.min.js', $dm->getPath('jquery'), false, false);
        $this->appendJs('pjBaseCore.js', $jsPath);
        $this->appendJs('js/bootstrap.min.js', $dm->getPath('bootstrap'), false, false);
        $this->appendJs('jquery.metisMenu.js', $dm->getPath('metis_menu'), false, false);
        $this->appendJs('jquery.slimscroll.min.js', $dm->getPath('slimscroll'), false, false);
        $this->appendJs('jquery.validate.min.js', $dm->getPath('validate'), false, false);
        $this->appendJs('jquery.gritter.min.js', $dm->getPath('gritter'), false, false);
        $this->appendJs('jquery.sparkline.min.js', $dm->getPath('sparkline'), false, false);
        $this->appendJs('toastr.min.js', $dm->getPath('toastr'), false, false);
        $this->appendJs('icheck.min.js', $dm->getPath('icheck'), false, false);
        $this->appendJs('spin.min.js', $dm->getPath('ladda'), false, false);
        $this->appendJs('ladda.min.js', $dm->getPath('ladda'), false, false);
        $this->appendJs('ladda.jquery.min.js', $dm->getPath('ladda'), false, false);
        $this->appendJs('sweetalert.min.js', $dm->getPath('sweetalert'), false, false);
        $this->appendJs('pace.min.js', $dm->getPath('pace'), false, false);
        $this->appendJs('jquery.bootstrap-touchspin.min.js', $dm->getPath('touchspin'), false, false);
        
        if (!$this->isInstaller())
        {
            $this->models['Option'] = pjBaseOptionModel::factory();
            $base_option_arr = $this->models['Option']->getPairs($this->getForeignId());
            $script_option_arr = pjOptionModel::factory()->getPairs($this->getForeignId());
            $this->option_arr = array_merge($base_option_arr, $script_option_arr);

            $this->option_arr['_show_demo_data_ui'] = true;
            $this->option_arr['_has_demo_data'] = false;
            if (!empty($this->option_arr['_show_demo_data_ui'])) {
                try {
                    if (class_exists('pjAdminSetup')) {
                        $this->option_arr['_has_demo_data'] = pjAdminSetup::hasDemoData();
                    } else {
                        $demoCheck = pjProductModel::factory()
                            ->where("t1.sku LIKE 'DEMO-%'")
                            ->limit(1)
                            ->findAll()
                            ->getData();
                        $this->option_arr['_has_demo_data'] = !empty($demoCheck);
                    }
                } catch (Exception $e) {
                    $this->option_arr['_has_demo_data'] = false;
                }
            }

            $this->set('option_arr', $this->option_arr);
            
            pjRegistry::getInstance()->set('options', $this->option_arr);
            if (isset($this->option_arr['o_timezone']))
            {
                pjTimezone::factory()->setAllTimezones($this->option_arr['o_timezone']);
            }
            pjCurrency::factory()->setCurrencyData();

            if (!$this->session->has($this->defaultLocale))
            {
                $locale_arr = pjLocaleModel::factory()->where('is_default', 1)->limit(1)->findAll()->getData();
                if (count($locale_arr) === 1)
                {
                    $this->setLocaleId($locale_arr[0]['id']);
                }
            }
            $this->loadSetFields(true);
            
            $is_ip_blocked = pjBase::isBlockedIp(pjUtil::getClientIp(), $this->option_arr);
            if($is_ip_blocked == true && !in_array($this->_get->toString('controller'), array('pjFront', 'pjFrontEnd', 'pjFrontPublic')))
            {
                $this->sendForbidden();
                return false;
            }
        }
        
        return true;
    }
    
    public function afterFilter()
    {
        if (!$this->isInstaller())
        {
            $menu_locale_arr =  pjLocaleModel::factory()
                ->select('t1.*, t2.file, t2.title')
                ->join('pjBaseLocaleLanguage', 't2.iso=t1.language_iso', 'left outer')
                ->where('t2.file IS NOT NULL')
                ->orderBy('t1.sort ASC')
                ->findAll()
                ->getDataPair('id');
            
            $this->set('menu_locale_arr', $menu_locale_arr);
            
            $default_language = NULL;
            foreach ($menu_locale_arr as $item)
            {
                if ($item['is_default'] == 1)
                {
                    $default_language = __('plugin_base_default_language', true) . ' - ' .  $item['name'];
                    break;
                }
            }
            $this->set('default_language', $default_language);
            
            $this->appendCss('style.css', $this->getConstant('pjBase', 'PLUGIN_CSS_PATH'));
            $this->appendCss('custom.css', $this->getConstant('pjBase', 'PLUGIN_CSS_PATH'));
            $this->appendCss('themes/'.$this->option_arr['o_base_theme'].'.css', $this->getConstant('pjBase', 'PLUGIN_CSS_PATH'));
            $this->appendJs('inspinia.js', $this->getConstant('pjBase', 'PLUGIN_JS_PATH'));

            if (!empty($this->option_arr['_show_demo_data_ui']) && !empty($this->option_arr['_has_demo_data'])) {
                $this->appendJs('pjAdminSetup.js');
            }

            $controllerName = $this->_get->toString('controller');
            if (
                defined('PJ_CSS_PATH')
                && !in_array($controllerName, array('pjFront', 'pjFrontEnd', 'pjFrontPublic', 'pjInstaller'))
            ) {
                if (method_exists($this, 'getAdminThemeColors')) {
                    $this->set('adminThemeColors', $this->getAdminThemeColors());
                }
                if ($this->isAuthScreen()) {
                    $this->appendCss('admin-auth-forms.css', PJ_CSS_PATH);
                } else {
                    $this->appendCss('admin.css', PJ_CSS_PATH);
                    $this->appendCss('admin-datagrid-listings.css', PJ_CSS_PATH);
                    $this->appendCss('admin-ui-global.css', PJ_CSS_PATH);
                    $this->appendCss('admin-modals-popups.css', PJ_CSS_PATH);
                    if ($controllerName === 'pjBaseOptions' && $this->_get->toString('action') === 'pjActionVisual') {
                        $this->appendCss('admin-visual-branding.css', PJ_CSS_PATH);
                    }
                }
            }
        }
    }

    public function getAdminThemeColors()
    {
        // Default = Workwear-style light admin theme (white sidebar, light surfaces)
        // with an ORANGE brand accent in place of Workwear's green.
        $defaults = array(
            'o_admin_primary'           => '#f97316',
            'o_admin_secondary'         => '#64748b',
            'o_admin_sidebar'           => '#ffffff',
            'o_admin_success'           => '#10b981',
            'o_admin_warning'           => '#f59e0b',
            'o_admin_info'              => '#3b6fa8',
            'o_admin_danger'            => '#ef4444',
            // Sidebar sub-colors
            'o_admin_sidebar_secondary' => '#f8fafc',
            'o_admin_sidebar_active'    => '#fff1e6',
            'o_admin_sidebar_text'      => '#64748b',
            'o_admin_sidebar_muted'     => '#94a3b8',
            // Content area colors
            'o_admin_main_bg'           => '#f8fafc',
            'o_admin_card_bg2'          => '#ffffff',
            'o_admin_table_border'      => '#e2e8f0',
            'o_admin_input_border'      => '#e2e8f0',
            'o_admin_main_text'         => '#0f172a',
            // Accent colors
            'o_admin_accent'            => '#f97316',
            'o_admin_link_color'        => '#f97316',
            // Independent table colors
            'o_admin_table_header_bg'  => '#f8fafc',
            'o_admin_table_row_bg'     => '#ffffff',
            'o_admin_table_row_alt'    => '#f8fafc',
            'o_admin_table_row_hover'  => '#fff7ed',
            'o_admin_table_text'       => '#334155',
            // Independent typography & icons
            'o_admin_heading_text'     => '#0f172a',
            'o_admin_muted_text'       => '#64748b',
            'o_admin_link_text'         => '#f97316',
            'o_admin_sidebar_icon'     => '#64748b',
            'o_admin_icon_color'       => '#64748b',
            // Topbar
            'o_admin_topbar_bg'        => '#ffffff',
            // Form inputs
            'o_admin_input_bg'         => '#ffffff',
            // Card / ibox border (independent from table row border)
            'o_admin_card_border'      => '#e2e8f0',
        );
        $colors = array();
        foreach ($defaults as $key => $default) {
            $value = isset($this->option_arr[$key]) ? $this->option_arr[$key] : $default;
            $colors[$key] = preg_match('/^#[0-9a-fA-F]{6}$/', $value) ? $value : $default;
        }
        $hexToRgb = function ($hex) {
            return array(hexdec(substr($hex, 1, 2)), hexdec(substr($hex, 3, 2)), hexdec(substr($hex, 5, 2)));
        };
        $transparent = function ($rgb, $alpha) {
            return sprintf('rgba(%d, %d, %d, %.2f)', $rgb[0], $rgb[1], $rgb[2], $alpha);
        };
        $lighten = function ($rgb, $factor) {
            return sprintf('#%02x%02x%02x',
                min(255, (int) ($rgb[0] + (255 - $rgb[0]) * $factor)),
                min(255, (int) ($rgb[1] + (255 - $rgb[1]) * $factor)),
                min(255, (int) ($rgb[2] + (255 - $rgb[2]) * $factor))
            );
        };
        $luminance = function ($rgb) {
            $r = $rgb[0] / 255;
            $g = $rgb[1] / 255;
            $b = $rgb[2] / 255;
            $r = $r <= 0.03928 ? $r / 12.92 : pow(($r + 0.055) / 1.055, 2.4);
            $g = $g <= 0.03928 ? $g / 12.92 : pow(($g + 0.055) / 1.055, 2.4);
            $b = $b <= 0.03928 ? $b / 12.92 : pow(($b + 0.055) / 1.055, 2.4);
            return 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
        };
        $contrastColor = function ($rgb) use ($luminance) {
            return $luminance($rgb) > 0.5 ? '#1a1a1a' : '#ffffff';
        };
        $smartDarken = function ($rgb, $startFactor) use ($luminance) {
            $factor = $startFactor;
            $result = array(
                max(0, (int) ($rgb[0] * $factor)),
                max(0, (int) ($rgb[1] * $factor)),
                max(0, (int) ($rgb[2] * $factor))
            );
            $maxIter = 12;
            while ($luminance($result) > 0.45 && $factor > 0.15 && $maxIter-- > 0) {
                $factor -= 0.10;
                $result = array(
                    max(0, (int) ($rgb[0] * $factor)),
                    max(0, (int) ($rgb[1] * $factor)),
                    max(0, (int) ($rgb[2] * $factor))
                );
            }
            if ($result[0] === $result[1] && $result[1] === $result[2] && $result[0] > 100) {
                $result = array(0x6B, 0x72, 0x80);
            }
            return sprintf('#%02x%02x%02x', $result[0], $result[1], $result[2]);
        };

        $primaryRgb            = $hexToRgb($colors['o_admin_primary']);
        $secondaryRgb          = $hexToRgb($colors['o_admin_secondary']);
        $sidebarRgb            = $hexToRgb($colors['o_admin_sidebar']);
        $successRgb            = $hexToRgb($colors['o_admin_success']);
        $warningRgb            = $hexToRgb($colors['o_admin_warning']);
        $infoRgb               = $hexToRgb($colors['o_admin_info']);
        $dangerRgb             = $hexToRgb($colors['o_admin_danger']);
        $sidebarSecondaryRgb   = $hexToRgb($colors['o_admin_sidebar_secondary']);
        $primaryDark           = $smartDarken($primaryRgb, 0.8);
        $primaryDarker         = $smartDarken($primaryRgb, 0.68);
        $primaryDarkRgb        = $hexToRgb($primaryDark);
        $accentRgb             = $hexToRgb($colors['o_admin_accent']);

        return array(
            '--admin-primary' => $colors['o_admin_primary'],
            '--admin-primary-dark' => $primaryDark,
            '--admin-primary-darker' => $primaryDarker,
            '--admin-primary-safe' => $primaryDark,
            '--admin-primary-light' => $transparent($primaryRgb, 0.25),
            '--admin-primary-lighter' => $transparent($primaryRgb, 0.12),
            '--admin-card-bg' => $transparent($primaryRgb, 0.05),
            '--admin-secondary' => $colors['o_admin_secondary'],
            '--admin-secondary-light' => $transparent($secondaryRgb, 0.25),
            '--admin-secondary-lighter' => $transparent($secondaryRgb, 0.12),
            '--admin-sidebar' => $colors['o_admin_sidebar'],
            '--admin-sidebar-hover' => $lighten($sidebarRgb, 0.05),
            '--admin-alert-bg' => $transparent($primaryRgb, 0.12),
            '--admin-modal-bg' => $transparent($primaryRgb, 0.06),
            '--admin-success' => $colors['o_admin_success'],
            '--admin-success-light' => $transparent($successRgb, 0.20),
            '--admin-success-lighter' => $transparent($successRgb, 0.10),
            '--admin-warning' => $colors['o_admin_warning'],
            '--admin-warning-light' => $transparent($warningRgb, 0.20),
            '--admin-warning-lighter' => $transparent($warningRgb, 0.10),
            '--admin-info' => $colors['o_admin_info'],
            '--admin-info-light' => $transparent($infoRgb, 0.20),
            '--admin-info-lighter' => $transparent($infoRgb, 0.10),
            '--admin-danger' => $colors['o_admin_danger'],
            '--admin-danger-light' => $transparent($dangerRgb, 0.20),
            '--admin-danger-lighter' => $transparent($dangerRgb, 0.10),
            '--pj-accent' => $colors['o_admin_secondary'],
            '--admin-on-primary'          => $contrastColor($primaryRgb),
            '--admin-on-secondary'        => $contrastColor($secondaryRgb),
            '--admin-on-sidebar'          => $contrastColor($sidebarRgb),
            '--admin-on-success'          => $contrastColor($successRgb),
            '--admin-on-warning'          => $contrastColor($warningRgb),
            '--admin-on-info'             => $contrastColor($infoRgb),
            '--admin-on-danger'           => $contrastColor($dangerRgb),
            // Sidebar sub-color variables
            '--admin-sidebar-secondary'   => $colors['o_admin_sidebar_secondary'],
            '--admin-sidebar-active-bg'   => $colors['o_admin_sidebar_active'],
            '--admin-sidebar-text'        => $colors['o_admin_sidebar_text'],
            '--admin-sidebar-muted'       => $colors['o_admin_sidebar_muted'],
            '--admin-sidebar-hover-bg'    => $lighten($sidebarSecondaryRgb, 0.06),
            // Content area variables
            '--admin-main-bg'             => $colors['o_admin_main_bg'],
            '--admin-card-bg-solid'       => $colors['o_admin_card_bg2'],
            '--admin-table-border'        => $colors['o_admin_table_border'],
            '--admin-input-border'        => $colors['o_admin_input_border'],
            '--admin-main-text'           => $colors['o_admin_main_text'],
            // Accent variables
            '--admin-accent'              => $colors['o_admin_accent'],
            '--admin-accent-light'        => $transparent($accentRgb, 0.15),
            '--admin-link'                => $colors['o_admin_link_color'],
            // Independent table variables
            '--admin-table-header-bg'   => $colors['o_admin_table_header_bg'],
            '--admin-table-header-text' => $contrastColor($hexToRgb($colors['o_admin_table_header_bg'])),
            '--admin-table-row-bg'      => $colors['o_admin_table_row_bg'],
            '--admin-table-row-alt-bg'  => $colors['o_admin_table_row_alt'],
            '--admin-table-row-hover'   => $colors['o_admin_table_row_hover'],
            '--admin-table-text'        => $colors['o_admin_table_text'],
            // Independent typography & icons
            '--admin-heading-text'      => $colors['o_admin_heading_text'],
            '--admin-muted-text'        => $colors['o_admin_muted_text'],
            '--admin-link-text'         => $colors['o_admin_link_text'],
            '--admin-sidebar-icon'      => $colors['o_admin_sidebar_icon'],
            '--admin-icon-color'        => $colors['o_admin_icon_color'],
            // Topbar (auto-contrast text)
            '--admin-topbar-bg'         => $colors['o_admin_topbar_bg'],
            '--admin-topbar-text'       => $contrastColor($hexToRgb($colors['o_admin_topbar_bg'])),
            // Form inputs (auto-contrast text)
            '--admin-input-bg'          => $colors['o_admin_input_bg'],
            '--admin-input-text'        => $contrastColor($hexToRgb($colors['o_admin_input_bg'])),
            // Card / ibox border
            '--admin-card-border'       => $colors['o_admin_card_border'],
        );
    }

    public static function getMailer($option_arr)
    {
    	$pjEmail = new pjEmail();
    	$pjEmail->setContentType("text/html");
    	
    	if ($option_arr['o_send_email'] == 'smtp')
    	{
    		$pjEmail
	    		->setTransport('smtp')
	    		->setSmtpSecure($option_arr['o_smtp_secure'])
	    		->setSmtpHost($option_arr['o_smtp_host'])
	    		->setSmtpPort($option_arr['o_smtp_port'])
	    		->setSmtpUser($option_arr['o_smtp_user'])
	    		->setSmtpPass($option_arr['o_smtp_pass'])
	    		->setSmtpAuthType($option_arr['o_smtp_auth']);
    	}
    	
    	if (pjValidation::pjActionEmail($option_arr['o_sender_email']))
    	{
    		$pjEmail->setSender($option_arr['o_sender_email']);
    		$pjEmail->setFrom($option_arr['o_sender_email'], $option_arr['o_sender_name']);
    	} else {
    	    $admin = pjAuthUserModel::factory()->find(1)->getData();
    	    $sender_name = @$admin['name'];
    	    if(!empty($option_arr['o_sender_name']))
    	    {
    	        $sender_name = $option_arr['o_sender_name'];
    	    }
    	    $pjEmail->setFrom(@$admin['email'], $sender_name);
    	}
    	
    	return $pjEmail;
    }
}
?>
