<?php
    /**
     * Front Class
     *
     * @package Wojo Framework
     * @author wojoscripts.com
     * @copyright 2023
     * @version 5.50: Front.php, v1.00 11/18/2023 10:54 AM Gewa Exp $
     *
     */
    if (!defined('_WOJO')) {
        die('Direct access to this location is not allowed.');
    }
    
    class Front
    {
        /**
         * index
         *
         * @return void
         */
        public function index(): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = str_replace('[COMPANY]', $core->company, Language::$word->META_WELCOME);
            
            $array = App::Product()->frontIndex();
            $tpl->special = ($array) ? array_slice($array, 0, 2) : null;
            $tpl->featured = ($array) ? array_slice($array, 2) : null;
            $tpl->home = Database::Go()->select(Content::pTable, array('title', 'body', 'keywords', 'description'))->where('page_type', 'home', '=')->where('active', 1, '=')->first()->run();
            
            $tpl->keywords = $tpl->home->keywords;
            $tpl->description = $tpl->home->description;
            $tpl->template = 'front/themes/' . $core->theme . '/index';
        }
        
        /**
         * page
         *
         * @param string $slug
         * @return void
         */
        public function page(string $slug): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = str_replace('[COMPANY]', $core->company, Language::$word->META_WELCOME);
            
            if (!$row = Database::Go()->select(Content::pTable)->where('slug', $slug, '=')->where('active', 1, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid slug ' . ($slug) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'front/themes/' . $core->theme . '/error';
            } else {
                $tpl->row = $row;
                
                if ($row->page_type == 'faq') {
                    $tpl->questions = Database::Go()->select(Content::fTable)->orderBy('sorting', 'ASC')->run();
                }
                
                if ($row->page_type == 'membership') {
                    $tpl->packages = Database::Go()->select(Membership::mTable)->where('active', 1, '=')->where('private', 1, '<')->orderBy('price', 'ASC')->run();
                }
                
                $tpl->title = Url::formatMeta($row->title);
                $tpl->keywords = $row->keywords;
                $tpl->description = $row->description;
                $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), $row->title];
                
                $tpl->template = 'front/themes/' . $core->theme . '/page';
            }
        }
        
        /**
         * login
         *
         * @return void
         */
        public function login(): void
        {
            if (App::Auth()->is_User()) {
                Url::redirect(Url::url('/dashboard'));
                exit;
            }
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            
            $tpl->dir = 'front/themes/' . $core->theme . '/full/';
            $tpl->title = str_replace('[COMPANY]', $core->company, Language::$word->META_M_LOGIN);
            $tpl->keywords = '';
            $tpl->description = '';
            
            $tpl->template = 'front/themes/' . $core->theme . '/login';
        }
        
        /**
         * news
         *
         * @return void
         */
        public function news(): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->NW_LATEST];
            $tpl->title = Language::$word->NW_LATEST . ' - ' . $core->company;
            $tpl->keywords = null;
            $tpl->description = null;
            
            $tpl->data = Database::Go()->select(Content::nTable)->where('active', 1, '=')->orderBy('created', 'DESC')->run();
            
            $tpl->template = 'front/themes/' . $core->theme . '/news';
        }
        
        /**
         * search
         *
         * @return void
         */
        public function search(): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_M_SEARCH];
            $tpl->title = Language::$word->META_M_SEARCH . ' - ' . $core->company;
            $tpl->keywords = null;
            $tpl->description = null;
            
            $tpl->keyword = Validator::get('keyword');
            $tpl->featured = ($tpl->keyword) ? App::Product()->search(Validator::sanitize($tpl->keyword, 'string', 20)) : null;
            
            $tpl->template = 'front/themes/' . $core->theme . '/search';
        }
        
        /**
         * register
         *
         * @return void
         */
        public function register(): void
        {
            if (App::Auth()->is_User()) {
                Url::redirect(Url::url('/dashboard'));
                exit;
            }
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            
            $tpl->dir = 'front/themes/' . $core->theme . '/full/';
            $tpl->title = str_replace('[COMPANY]', $core->company, Language::$word->META_M_REGISTER);
            $tpl->keywords = '';
            $tpl->description = '';
            
            $tpl->custom_fields = Content::renderCustomFieldsFront(0, 'profile');
            $tpl->countries = $core->enable_tax ? Database::Go()->select(Content::cnTable)->orderBy('sorting', 'DESC')->run() : null;
            
            $tpl->template = 'front/themes/' . $core->theme . '/register';
        }
        
        /**
         * registration
         *
         * @return void
         * @throws NotFoundException
         * @throws \PHPMailer\PHPMailer\Exception
         */
        public function registration(): void
        {
            $validate = Validator::run($_POST);
            $core = App::Core();
            $validate
                ->set('fname', Language::$word->FNAME)->required()->string()->min_len(2)->max_len(60)
                ->set('lname', Language::$word->LNAME)->required()->string()->min_len(2)->max_len(60)
                ->set('password', Language::$word->PASSWORD)->required()->string()->min_len(8)->max_len(16)
                ->set('email', Language::$word->EMAIL)->required()->email()
                ->set('agree', Language::$word->PRIVACY)->required()->numeric()
                ->set('captcha', Language::$word->CAPTCHA)->required()->numeric()->equals(Session::get('wcaptcha'))->exact_len(5);
            
            if ($core->enable_tax) {
                $validate
                    ->set('address', Language::$word->ADDRESS)->required()->string()->min_len(3)->max_len(80)
                    ->set('city', Language::$word->CITY)->required()->string()->min_len(2)->max_len(60)
                    ->set('zip', Language::$word->ZIP)->required()->string()->min_len(3)->max_len(30)
                    ->set('state', Language::$word->STATE)->required()->string()->min_len(2)->max_len(60)
                    ->set('country', Language::$word->COUNTRY)->required()->string()->exact_len(2);
            }
            
            $safe = $validate->safe();
            
            if (strlen($safe->email)) {
                if (Auth::emailExists($safe->email)) {
                    Message::$msgs['email'] = Language::$word->EMAIL_R2;
                }
            }
            Content::verifyCustomFields('profile');
            if (count(Message::$msgs) === 0) {
                $hash = Auth::doHash($safe->password);
                $username = Utility::randomString();
                
                if ($core->reg_verify == 1) {
                    $active = 't';
                } elseif ($core->auto_verify == 0) {
                    $active = 'n';
                } else {
                    $active = 'y';
                }
                
                $data = array(
                    'username' => $username,
                    'email' => $safe->email,
                    'lname' => $safe->lname,
                    'fname' => $safe->fname,
                    'hash' => $hash,
                    'type' => 'member',
                    'token' => Utility::randNumbers(),
                    'active' => $active,
                    'userlevel' => 1,
                );
                
                if ($core->enable_tax) {
                    $data['address'] = $safe->address;
                    $data['city'] = $safe->city;
                    $data['state'] = $safe->state;
                    $data['zip'] = $safe->zip;
                    $data['country'] = $safe->country;
                }
                
                $last_id = Database::Go()->insert(User::mTable, $data)->run();
                
                //Start Custom Fields
                $fl_array = Utility::array_key_exists_wildcard($_POST, 'custom_*', 'key-value');
                $dataArray = array();
                if ($fl_array) {
                    $fields = Database::Go()->select(Content::cfTable)->where('section', 'profile', '=')->run();
                    foreach ($fields as $row) {
                        $dataArray[] = array(
                            'user_id' => $last_id,
                            'field_id' => $row->id,
                            'field_name' => $row->name,
                        );
                    }
                    Database::Go()->batch(Content::cfdTable, $dataArray)->run();
                    
                    foreach ($fl_array as $key => $val) {
                        $cfdata['field_value'] = Validator::sanitize($val);
                        Database::Go()->update(Content::cfdTable, $cfdata)->where('user_id', $last_id, '=')->where('field_name', str_replace('custom_', '', $key), '=')->run();
                    }
                }
                
                $mailer = Mailer::sendMail();
                
                if ($core->reg_verify == 1) {
                    $message = Language::$word->M_INFO7;
                    $json['redirect'] = SITEURL;
                    $tpl = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', 'regMail', '=')->first()->run();
                    
                    $body = str_replace(array(
                        '[LOGO]',
                        '[DATE]',
                        '[COMPANY]',
                        '[SITE_NAME]',
                        '[NAME]',
                        '[USERNAME]',
                        '[PASSWORD]',
                        '[LINK]',
                        '[FB]',
                        '[TW]',
                        '[CEMAIL]',
                        '[SITEURL]'
                    ), array(
                        $core->plogo,
                        date('Y'),
                        $core->company,
                        $core->site_name,
                        $safe->fname . ' ' . $safe->lname,
                        $safe->email,
                        $safe->password,
                        Url::url('/activation', '?token=' . $data['token'] . '&email=' . $data['email']),
                        $core->social->facebook,
                        $core->social->twitter,
                        $core->site_email,
                        SITEURL
                    ), $tpl->body);
                } elseif ($core->auto_verify == 0) {
                    $message = Language::$word->M_INFO7;
                    $json['redirect'] = SITEURL;
                    
                    $tpl = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', 'regMailPending', '=')->first()->run();
                    
                    $body = str_replace(array(
                        '[LOGO]',
                        '[DATE]',
                        '[COMPANY]',
                        '[SITE_NAME]',
                        '[NAME]',
                        '[USERNAME]',
                        '[PASSWORD]',
                        '[FB]',
                        '[TW]',
                        '[CEMAIL]',
                        '[SITEURL]'
                    ), array(
                        $core->plogo,
                        date('Y'),
                        $core->company,
                        $core->site_name,
                        $safe->fname . ' ' . $safe->lname,
                        $safe->email,
                        $safe->password,
                        $core->social->facebook,
                        $core->social->twitter,
                        $core->site_email,
                        SITEURL
                    ), $tpl->body);
                } else {
                    //login user
                    App::Auth()->login($safe->email, $safe->password, true);
                    $message = Language::$word->M_INFO8;
                    $json['redirect'] = Url::url('/dashboard');
                    
                    $tpl = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', 'welcomeEmail', '=')->first()->run();
                    
                    $body = str_replace(array(
                        '[LOGO]',
                        '[DATE]',
                        '[COMPANY]',
                        '[SITE_NAME]',
                        '[NAME]',
                        '[USERNAME]',
                        '[PASSWORD]',
                        '[LINK]',
                        '[FB]',
                        '[TW]',
                        '[CEMAIL]',
                        '[SITEURL]'
                    ), array(
                        $core->plogo,
                        date('Y'),
                        $core->company,
                        $core->site_name,
                        $safe->fname . ' ' . $safe->lname,
                        $safe->email,
                        $safe->password,
                        Url::url(''),
                        $core->social->facebook,
                        $core->social->twitter,
                        $core->site_email,
                        SITEURL
                    ), $tpl->body);
                }
                $mailer->Subject = $tpl->subject;
                $mailer->Body = $body;
                $mailer->setFrom($core->site_email, $core->company);
                $mailer->addAddress($data['email'], $data['fname'] . ' ' . $data['lname']);
                $mailer->isHTML();
                $mailer->send();
                
                if ($core->notify_admin) {
                    $mailer2 = Mailer::sendMail();
                    $tpl2 = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', 'notifyAdmin', '=')->first()->run();
                    
                    $body2 = str_replace(array(
                        '[LOGO]',
                        '[DATE]',
                        '[COMPANY]',
                        '[SITE_NAME]',
                        '[EMAIL]',
                        '[NAME]',
                        '[IP]',
                        '[FB]',
                        '[TW]',
                        '[CEMAIL]',
                        '[SITEURL]'
                    ), array(
                        $core->plogo,
                        date('Y'),
                        $core->company,
                        $core->site_name,
                        $safe->email,
                        $data['fname'] . ' ' . $data['lname'],
                        Url::getIP(),
                        $core->social->facebook,
                        $core->social->twitter,
                        $core->site_email,
                        SITEURL
                    ), $tpl2->body);
                    
                    $mailer2->Subject = $tpl2->subject;
                    $mailer2->Body = $body2;
                    $mailer2->setFrom($core->site_email, $core->company);
                    $mailer2->addAddress($core->site_email, $core->company);
                    $mailer2->isHTML();
                    $mailer2->send();
                }
                if (Database::Go()->affected()) {
                    $json['type'] = 'success';
                    $json['title'] = Language::$word->SUCCESS;
                    $json['message'] = $message;
                } else {
                    $json['type'] = 'error';
                    $json['title'] = Language::$word->ERROR;
                    $json['message'] = Language::$word->MSG_INFO06;
                }
                print json_encode($json);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * dashboard
         *
         * @return void
         */
        public function dashboard(): void
        {
            if (!App::Auth()->is_User()) {
                Url::redirect(Url::url('/login'));
                exit;
            }
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = Language::$word->META_M_MYDOWNS . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_M_MYDOWNS];
            $tpl->keywords = '';
            $tpl->description = '';
            
            $tpl->data = Stats::userDownloads();
            
            $tpl->template = 'front/themes/' . $core->theme . '/dashboard';
        }
        
        /**
         * view
         *
         * @param string $token
         * @return void
         */
        public function view(string $token): void
        {
            if (!App::Auth()->is_User()) {
                Url::redirect(Url::url('/login'));
                exit;
            }
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = Language::$word->META_M_MYDOWNS . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_M_MYDOWNS];
            $tpl->keywords = '';
            $tpl->description = '';
            
            $tpl->row = Product::fileAccess(Utility::decode($token));
            if ($tpl->row) {
                $tpl->data = Product::relatedFiles(explode(',', $tpl->row->files));
                $tpl->stats = Stats::fileStats($tpl->row);
            } else {
                $tpl->data = null;
                $tpl->stats = null;
            }
            
            $tpl->template = 'front/themes/' . $core->theme . '/view';
        }
        
        /**
         * membership
         *
         * @return void
         */
        public function membership(): void
        {
            if (!App::Auth()->is_User()) {
                Url::redirect(Url::url('/login'));
                exit;
            }
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            
            $tpl->title = Language::$word->META_M_MEMBERSHIPS . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_DASH, Language::$word->MEMBERSHIPS];
            $tpl->keywords = '';
            $tpl->description = '';
            
            $tpl->data = Database::Go()->select(Membership::mTable)->where('active', 1, '=')->where('private', 1, '<')->orderBy('price', 'ASC')->run();
            $tpl->user = Database::Go()->select(User::mTable, array('membership_id'))->where('id', App::Auth()->uid, '=')->first()->run();
            App::Auth()->membership_id = $tpl->user->membership_id;
            
            $tpl->template = 'front/themes/' . $core->theme . '/memberships';
        }
        
        /**
         * profile
         *
         * @return void
         */
        public function profile(): void
        {
            if (!App::Auth()->is_User()) {
                Url::redirect(Url::url('/login'));
                exit;
            }
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = Language::$word->META_M_ACCNT . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_DASH, Language::$word->META_M_ACCNT];
            $tpl->keywords = '';
            $tpl->description = '';
            
            $tpl->row = Database::Go()->select(User::mTable)->where('id', App::Auth()->uid, '=')->first()->run();
            $tpl->custom_fields = Content::renderCustomFieldsFront($tpl->row->id, 'profile');
            if ($core->enable_tax) {
                $tpl->countries = App::Content()->getCountryList();
            }
            
            $tpl->template = 'front/themes/' . $core->theme . '/profile';
        }
        
        /**
         * updateProfile
         *
         * @return void
         */
        public function updateProfile(): void
        {
            $core = App::Core();
            $validate = Validator::run($_POST);
            $validate
                ->set('fname', Language::$word->FNAME)->required()->string()->min_len(2)->max_len(60)
                ->set('lname', Language::$word->LNAME)->required()->string()->min_len(2)->max_len(60)
                ->set('email', Language::$word->EMAIL)->required()->email()
                ->set('newsletter', Language::$word->USR_NLETTER)->required()->numeric();
            
            if ($core->enable_tax) {
                $validate
                    ->set('address', Language::$word->ADDRESS)->required()->string()->min_len(3)->max_len(80)
                    ->set('city', Language::$word->CITY)->required()->string()->min_len(2)->max_len(60)
                    ->set('zip', Language::$word->ZIP)->required()->string()->min_len(3)->max_len(30)
                    ->set('state', Language::$word->STATE)->required()->string()->min_len(2)->max_len(60)
                    ->set('country', Language::$word->COUNTRY)->required()->string()->exact_len(2);
            }
            
            $thumb = File::upload('avatar', 512000, 'png,jpg,jpeg');
            Content::verifyCustomFields('profile');
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'email' => $safe->email,
                    'lname' => $safe->lname,
                    'fname' => $safe->fname,
                    'newsletter' => $safe->newsletter,
                );
                if (App::Core()->enable_tax) {
                    $data['address'] = $safe->address;
                    $data['city'] = $safe->city;
                    $data['zip'] = $safe->zip;
                    $data['state'] = $safe->state;
                    $data['country'] = $safe->country;
                }
                
                if (strlen($_POST['password'])) {
                    $data['hash'] = Auth::doHash($_POST['password']);
                }
                
                if (array_key_exists('avatar', $_FILES)) {
                    $thumbPath = UPLOADS . '/avatars/';
                    if (Auth::$udata->avatar != '') {
                        File::deleteFile(UPLOADS . '/avatars/' . Auth::$udata->avatar);
                    }
                    $result = File::process($thumb, $thumbPath, 'AVT_');
                    App::Auth()->avatar = Session::set('avatar', $result['fname']);
                    $data['avatar'] = $result['fname'];
                }
                
                Database::Go()->update(User::mTable, $data)->where('id', App::Auth()->uid, '=')->run();
                
                // Start Custom Fields
                $fl_array = Utility::array_key_exists_wildcard($_POST, 'custom_*', 'key-value');
                if ($fl_array) {
                    foreach ($fl_array as $key => $val) {
                        $cfdata['field_value'] = Validator::sanitize($val);
                        Database::Go()->update(Content::cfdTable, $cfdata)->where('user_id', App::Auth()->uid, '=')->where('field_name', str_replace('custom_', '', $key), '=')->run();
                    }
                }
                
                Message::msgReply(true, 'success', str_replace('[NAME]', '', Language::$word->USR_UPDATE_OK));
                if (Database::Go()->affected()) {
                    Auth::$udata->email = Session::set('email', $data['email']);
                    Auth::$udata->fname = Session::set('fname', $data['fname']);
                    Auth::$udata->lname = Session::set('lname', $data['lname']);
                    Auth::$udata->name = Session::set('name', $data['fname'] . ' ' . $data['lname']);
                    if ($core->enable_tax) {
                        Auth::$udata->country = Session::set('country', $data['country']);
                    }
                }
            } else {
                Message::msgSingleStatus();
            }
        }
        public function history(): void
        {
            if (!App::Auth()->is_User()) {
                Url::redirect(Url::url('/login'));
                exit;
            }
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = Language::$word->META_M_MHISTORY . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_DASH, Language::$word->META_M_MHISTORY];
            $tpl->keywords = '';
            $tpl->description = '';
            
            $tpl->data = Stats::userHistory(App::Auth()->uid, 'expire');
            $tpl->totals = Stats::userTotals();
            
            $tpl->template = 'front/themes/' . $core->theme . '/history';
        }
        /**
         * buyMembership
         *
         * @return void
         */
        public function buyMembership(): void
        {
            if ($row = Database::Go()->select(Membership::mTable)->where('id', Filter::$id, '=')->where('private', 1, '<')->first()->run()) {
                $gaterows = Database::Go()->select(Admin::gTable)->where('active', 1, '=')->run();
                
                if ($row->price == 0) {
                    $data = array(
                        'membership_id' => $row->id,
                        'mem_expire' => Date::calculateDays($row->id),
                    );
                    
                    Database::Go()->update(User::mTable, $data)->where('id', App::Auth()->uid, '=')->run();
                    Auth::$udata->membership_id = Session::set('membership_id', $row->id);
                    Auth::$udata->mem_expire = Session::set('mem_expire', $data['mem_expire']);
                    
                    $json['message'] = Message::msgSingleOk(str_replace('[NAME]', $row->title, Language::$word->MSG_INFO09));
                } else {
                    //$recurring = ($row->recurring) ? Language::$word->YES : Language::$word->NO;
                    Database::Go()->delete(Content::xTable)->where('user_m_id', App::Auth()->uid, '=')->run();
                    $tax = Content::calculateTax();
                    
                    $data = array(
                        'user_m_id' => App::Auth()->uid,
                        'membership_id' => $row->id,
                        'originalprice' => $row->price,
                        'tax' => Validator::sanitize($tax, 'float'),
                        'totaltax' => Validator::sanitize($row->price * $tax, 'float'),
                        'total' => $row->price,
                        'totalprice' => Validator::sanitize($tax * $row->price + $row->price, 'float'),
                    );
                    Database::Go()->insert(Content::xTable, $data)->run();
                    $cart = Membership::getCart(App::Auth()->uid);
                    
                    $tpl = App::View(THEMEBASE . '/snippets/');
                    $tpl->row = $row;
                    $tpl->gateways = $gaterows;
                    $tpl->cart = $cart;
                    $tpl->template = 'loadSummary';
                    $json['message'] = $tpl->render();
                }
            } else {
                $json['type'] = 'error';
            }
            print json_encode($json);
        }
        
        /**
         * selectGateway
         *
         * @return void
         */
        public function selectGateway(): void
        {
            
            if ($cart = Membership::getCart(App::Auth()->uid)) {
                $gateway = Database::Go()->select(Admin::gTable)->where('id', Filter::$id, '=')->where('active', 1, '=')->first()->run();
                $row = Database::Go()->select(Membership::mTable)->where('id', $cart->membership_id, '=')->first()->run();
                $tpl = App::View(BASEPATH . 'gateways/' . $gateway->dir . '/');
                $tpl->cart = $cart;
                $tpl->core = App::Core();
                $tpl->gateway = $gateway;
                $tpl->row = $row;
                $tpl->template = 'form';
                $json['message'] = $tpl->render();
            } else {
                $json['message'] = Message::msgSingleError(Language::$word->SYSERROR);
            }
            print json_encode($json);
        }
        
        /**
         * compare
         *
         * @return void
         */
        public function compare(): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = Language::$word->FRONT_COMPARE . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->FRONT_COMPARE];
            $tpl->keywords = '';
            $tpl->description = '';
            $tpl->data = null;
            
            if (Session::get('compare')) {
                $ids = Utility::implodeFields(Session::get('compare'));
                $tpl->data = App::Product()->compare($ids);
            }
            
            $tpl->template = 'front/themes/' . $core->theme . '/compare';
        }
        
        /**
         * wishlist
         *
         * @return void
         */
        public function wishlist(): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = Language::$word->META_M_WISHLIST . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_M_WISHLIST];
            $tpl->keywords = '';
            $tpl->description = '';
            $tpl->data = null;
            
            if (App::Auth()->is_User()) {
                $sql = "
                SELECT m.id, m.title, m.slug, m.thumb, MAX(m.created) as m_created, m.is_sale, m.price, m.sprice, m.type, m.token, m.affiliate, m.type, m.membership_id,
                       GROUP_CONCAT(mx.title SEPARATOR ', ') as memberships
                  FROM `" . Content::wTable . '` as w
                  LEFT JOIN `' . Product::mTable . '` as m ON m.id = w.product_id
                  LEFT JOIN `' . Membership::mTable . '` as mx ON FIND_IN_SET(mx.id, m.membership_id)
                  WHERE m.active = ?
                  AND w.user_id = ?
                  GROUP BY m.id
                  ORDER BY m_created DESC
                ';
                $tpl->data = Database::Go()->rawQuery($sql, array(1, App::Auth()->uid))->run();
            } else {
                if (Session::get('wishlist')) {
                    $ids = Utility::implodeFields(Session::get('wishlist'));
                    $sql = 'SELECT id, slug, title, thumb, is_sale, price, sprice, affiliate, type, token, membership_id FROM `' . Product::mTable . '` WHERE id IN (' . $ids . ')';
                    $tpl->data = Database::Go()->rawQuery($sql)->run();
                }
            }
            
            $tpl->template = 'front/themes/' . $core->theme . '/wishlist';
        }
        
        /**
         * passReset
         *
         * @return void
         * @throws \PHPMailer\PHPMailer\Exception
         */
        public function passReset(): void
        {
            $validate = Validator::run($_POST);
            
            $validate->set('email', Language::$word->EMAIL)->required()->email();
            $safe = $validate->safe();
            
            $json['type'] = 'error';
            $json['title'] = Language::$word->ERROR;
            $json['message'] = Language::$word->EMAIL_R4;
            
            if (strlen($safe->email)) {
                $row = Database::Go()->select(User::mTable, array('email', 'fname', 'lname', 'id'))
                    ->where('email', $safe->email, '=')
                    ->where('active', 'y', '=')
                    ->first()->run();
                if (!$row) {
                    Message::$msgs['fname'] = Language::$word->EMAIL_R4;
                }
            }
            
            if (count(Message::$msgs) === 0) {
                $row = Database::Go()->select(User::mTable, array('email', 'fname', 'lname', 'id', 'type'))
                    ->where('email', $safe->email, '=')
                    ->where('active', 'y', '=')
                    ->first()->run();
                
                $token = substr(md5(uniqid(rand(), true)), 0, 10);
                $template = ($row->type == 'member') ? 'userPassReset ' : 'adminPassReset';
                $core = App::Core();
                $mailer = Mailer::sendMail();
                $tpl = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', $template, '=')->first()->run();
                
                $body = str_replace(array(
                    '[LOGO]',
                    '[NAME]',
                    '[DATE]',
                    '[COMPANY]',
                    '[SITE_NAME]',
                    '[LINK]',
                    '[IP]',
                    '[FB]',
                    '[TW]',
                    '[CEMAIL]',
                    '[SITEURL]'
                ), array(
                    $core->plogo,
                    $row->fname . ' ' . $row->lname,
                    date('Y'),
                    $core->company,
                    $core->site_name,
                    Url::url('/password', $token),
                    Url::getIP(),
                    $core->social->facebook,
                    $core->social->twitter,
                    $core->site_email,
                    SITEURL
                ), $tpl->body);
                
                $mailer->setFrom($core->site_email, $core->company);
                $mailer->addAddress($row->email, $row->fname . ' ' . $row->lname);
                
                $mailer->isHTML();
                $mailer->Subject = $tpl->subject;
                $mailer->Body = $body;
                
                Database::Go()->update(User::mTable, array('token' => $token))->where('id', $row->id, '=')->run();
                
                if ($mailer->send()) {
                    $json['type'] = 'success';
                    $json['title'] = Language::$word->SUCCESS;
                    $json['message'] = Language::$word->PASSWORD_RES_D;
                    print json_encode($json);
                }
            } else {
                $json['type'] = 'error';
                $json['title'] = Language::$word->ERROR;
                $json['message'] = Language::$word->EMAIL_R5;
                print json_encode($json);
            }
        }
        
        /**
         * password
         *
         * @param string $token
         * @return void
         */
        public function password(string $token): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/full/';
            $tpl->title = Language::$word->META_M_PASSRESET;
            $tpl->keywords = null;
            $tpl->description = null;
            
            if (!$row = Database::Go()->select(User::mTable)->where('token', $token, '=')->where('active', 'y', '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid token ' . ($token) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                    $tpl->template = 'front/themes/' . $core->theme . '/error';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                    $tpl->title = Language::$word->META_ERROR;
                    $tpl->template = 'front/themes/' . $core->theme . '/404';
                }
            } else {
                $tpl->row = $row;
                $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->PASSWORD_RES];
                
                $tpl->template = 'front/themes/' . $core->theme . '/password';
            }
        }
        
        /**
         * passwordChange
         *
         * @return void
         */
        public function passwordChange(): void
        {
            $validate = Validator::run($_POST);
            
            $validate
                ->set('token', 'Token')->required()->string()
                ->set('password', Language::$word->NEWPASS)->required()->string()->min_len(8)->max_len(12);
            
            $safe = $validate->safe();
            
            if (!$row = Database::Go()->select(User::mTable, array('id', 'type'))->where('token', $safe->token, '=')->first()->run()) {
                Message::$msgs['token'] = 'Invalid Token.';
                $json['title'] = Language::$word->ERROR;
                $json['message'] = 'Invalid Token.';
                $json['type'] = 'error';
            }
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'hash' => Auth::doHash($safe->password),
                    'token' => 0,
                );
                
                Database::Go()->update(User::mTable, $data)->where('id', $row->id, '=')->run();
                $json['type'] = 'success';
                $json['title'] = Language::$word->SUCCESS;
                $json['redirect'] = ($row->type == 'member') ? Url::url('/login') : Url::url('/admin');
                $json['message'] = Language::$word->USR_PASSUPDATE_OK2;
                print json_encode($json);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * activation
         *
         * @return void
         */
        public function activation(): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/full/';
            $tpl->title = Language::$word->META_M_ACC_ACT;
            $tpl->keywords = null;
            $tpl->description = null;
            
            if (Validator::get('token') and Validator::get('email')) {
                $validate = Validator::run($_GET);
                $validate
                    ->set('email', Language::$word->EMAIL)->required()->email()
                    ->set('token', Language::$word->MSG_INFO07)->required()->string();
                
                $safe = $validate->safe();
                if (count(Message::$msgs) === 0) {
                    if ($row = Database::Go()->select(User::mTable, array('id'))->where('email', $safe->email, '=')->where('token', $safe->token, '=')->first()->run()) {
                        Database::Go()->update(User::mTable, array('active' => 'y', 'token' => 0))->where('id', $row->id, '=')->run();
                        Url::redirect(Url::url('/activation', '?done=true'));
                    }
                }
            }
            
            $tpl->template = 'front/themes/' . $core->theme . '/activation';
        }
        
        public function validate(): void
        {
            if (!App::Auth()->is_User()) {
                Url::redirect(Url::url('/login'));
                exit;
            }
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = Language::$word->META_M_ACCNT . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_DASH, Language::$word->META_M_ACCNT];
            $tpl->keywords = '';
            $tpl->description = '';
            $tpl->data = null;
            
            $tpl->template = 'front/themes/' . $core->theme . '/_validate';
        }
        
        /**
         * processContact
         *
         * @return void
         * @throws \PHPMailer\PHPMailer\Exception
         */
        public function processContact(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('name', Language::$word->NAME)->required()->string()->min_len(2)->max_len(60)
                ->set('notes', Language::$word->MESSAGE)->required()->string(true, true)->min_len(10)->max_len(200)
                ->set('email', Language::$word->EMAIL)->required()->email()
                ->set('agree', Language::$word->PRIVACY)->required()->numeric()
                ->set('captcha', Language::$word->CAPTCHA)->required()->numeric()->exact_len(5);
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $row = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', 'contact', '=')->first()->run();
                $mailer = Mailer::sendMail();
                $core = App::Core();
                
                $body = str_replace(array(
                    '[LOGO]',
                    '[NAME]',
                    '[EMAIL]',
                    '[PHONE]',
                    '[MAILSUBJECT]',
                    '[MESSAGE]',
                    '[IP]',
                    '[DATE]',
                    '[COMPANY]',
                    '[SITE_NAME]',
                    '[FB]',
                    '[TW]',
                    '[CEMAIL]',
                    '[SITEURL]'
                ), array(
                    $core->plogo,
                    $safe->name,
                    $safe->email,
                    $safe->phone,
                    $safe->subject,
                    $safe->notes,
                    Url::getIP(),
                    date('Y'),
                    $core->company,
                    $core->site_name,
                    $core->social->facebook,
                    $core->social->twitter,
                    $core->site_email,
                    SITEURL
                ), $row->body);
                
                $mailer->setFrom($core->site_email, $core->company);
                $mailer->addAddress($core->site_email, $core->company);
                $mailer->addReplyTo($safe->email, $safe->name);
                
                $mailer->isHTML();
                $mailer->Subject = $row->subject;
                $mailer->Body = $body;
                
                if ($mailer->send()) {
                    $json['type'] = 'success';
                    $json['title'] = Language::$word->SUCCESS;
                    $json['redirect'] = Url::url('/content', $core->page_slugs->home[0]->page_type);
                    $json['message'] = Language::$word->CONTACT_OK;
                } else {
                    $json['type'] = 'error';
                    $json['title'] = Language::$word->ERROR;
                    $json['message'] = Language::$word->CONTACT_ERR;
                }
                print json_encode($json);
            } else {
                Message::msgSingleStatus();
            }
        }
    }