<?php error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED);
define('FOPEN_WRITE_CREATE_DESTRUCTIVE', 'wb');
define('UPDATE_URL', 'https://update.uniquecoder.com/');
define('FILE_READ_MODE', 0644);
define('FILE_WRITE_MODE', 0666);
ini_set('max_execution_time', 30000000);
if (function_exists('mysqli_report')) {
    mysqli_report(MYSQLI_REPORT_OFF);
}

class Install
{
    public function go()
    {
        $debug = '';
        $bug_error = '';
        $step = 1;
        if (isset($_POST) && !empty($_POST)) {
            if (isset($_POST['step']) && $_POST['step'] == 2) {
                if ($_POST['envato_username'] == '') {
                    $bug_error = 'We need your envato username to verify The purchase';
                } elseif (filter_var($_POST['support_email'], FILTER_VALIDATE_EMAIL) === false) {
                    $bug_error = 'We need your valid email to Support you';
                } elseif ($_POST['purchase_code'] == '') {
                    $bug_error = 'Enter your envato purchase code here';
                }
                $step = 2;
                $env_data = $this->remote_get_contents($_POST);
                $result = json_decode($env_data, true);
                if ($result['success'] == true) {
                    $debug = "Congratulation and Thanks for purchasing it.your setup is almost done";
                    $step = 3;
                } else {
                    $bug_error = $result['error'];
                    $step = 2;
                }
            } elseif (isset($_POST['permissions_success'])) {
                $step = 2;
            } elseif (isset($_POST['step']) && $_POST['step'] == 3) {
                $step = 3;
                $p = array();
                if ($_POST['hostname'] == '') {
                    $bug_error = 'Hostname is required';
                } elseif ($_POST['database'] == '') {
                    $bug_error = 'Enter database name';
                } elseif ($_POST['db_password'] == '' && !$this->is_localhost()) {
                    $bug_error = 'Enter database password';
                } elseif ($_POST['db_username'] == '') {
                    $bug_error = 'Enter database username';
                } elseif ($_POST['app_base_url'] == '' || filter_var($_POST['app_base_url'], FILTER_VALIDATE_URL) === false) {
                    $bug_error = 'Enter a valid application URL';
                } elseif ($_POST['app_enc_key'] == '') {
                    $bug_error = 'Enter an encryption key';
                }
                if ($bug_error === '') {
                    $link = $this->connect_db($_POST);
                    if (!$link) {
                        $bug_error .= "Error: Unable to connect to MySQL." . PHP_EOL;
                        $bug_error .= "Debugging errno: " . mysqli_connect_errno() . PHP_EOL;
                        $bug_error .= "Debugging error: " . mysqli_connect_error() . PHP_EOL;
                    } else {
                        $debug .= "Success: A proper connection to MySQL was made! The " . $_POST['database'] . " database is great." . PHP_EOL;
                        $debug .= "Host information: " . mysqli_get_host_info($link) . PHP_EOL;
                        $step = 4;
                        mysqli_close($link);
                    }
                }
            } elseif (isset($_POST['step']) && $_POST['step'] == 4) {
                if ($_POST['admin_email'] == '') {
                    $bug_error = 'Enter admin email address';
                } elseif (filter_var($_POST['admin_email'], FILTER_VALIDATE_EMAIL) === false) {
                    $bug_error = 'Enter valid email address';
                } elseif ($_POST['admin_password'] == '') {
                    $bug_error = 'Enter admin password';
                } elseif ($_POST['admin_password'] != $_POST['confirm_password']) {
                    $bug_error = 'Your password not match';
                }
                $step = 4;
            }
            if ($bug_error === '' && isset($_POST['step']) && $_POST['step'] == 4) {
                $env_data = $this->remote_get_contents($_POST, true);
                $result = json_decode($env_data, true);
                if (!empty($result['success'])) {
                    $success = $this->install_db($_POST, $result['all_table']);
                    if (!empty($success)) {
                        $link = $this->connect_db($_POST);
                        if (!$link) {
                            $bug_error = "Error: Unable to connect to MySQL." . PHP_EOL;
                            $bug_error .= "Debugging errno: " . mysqli_connect_errno() . PHP_EOL;
                            $bug_error .= "Debugging error: " . mysqli_connect_error() . PHP_EOL;
                            $step = 4;
                            require_once('html.php');
                            return;
                        }
                        if (!$this->write_app_config($_POST)) {
                            $bug_error = 'Unable to write application config. Please check application/config permissions.';
                            $step = 4;
                            mysqli_close($link);
                            require_once('html.php');
                            return;
                        }
                        $this->clean_up_db_query($link);

                        $fullname = $this->db_escape($link, $_POST['admin_fullname']);
                        $username = $this->db_escape($link, $_POST['admin_username']);
                        $password = $this->db_escape($link, $this->hash($_POST['admin_password'], $_POST['app_enc_key']));
                        $user_email = $this->db_escape($link, $_POST['admin_email']);
                        $company_name = $this->db_escape($link, $_POST['company_name']);
                        $company_email = $this->db_escape($link, $_POST['company_email']);
                        $timezone = $this->db_escape($link, $_POST['timezone']);
                        $created = date('Y-m-d H:i:s');

                        $sql = "INSERT INTO tbl_users(username,email,password,role_id,activated,created) VALUES ('$username','$user_email','$password',1,1,'$created')";
                        mysqli_query($link, $sql);
                        $last_id = mysqli_insert_id($link);
                        if (empty($last_id) || $last_id == 0) {
                            $last_id = 1;
                        }
                        $sql = "INSERT INTO tbl_account_details (fullname,user_id) VALUES('$fullname','$last_id')";
                        mysqli_query($link, $sql);


                        $sql = "UPDATE tbl_config SET value='$company_name' WHERE config_key='company_name'";
                        mysqli_query($link, $sql);

                        $sql = "UPDATE tbl_config SET value='$company_name' WHERE config_key='company_legal_name'";
                        mysqli_query($link, $sql);

                        $sql = "UPDATE tbl_config SET value='$company_name' WHERE config_key='website_name'";
                        mysqli_query($link, $sql);

                        $sql = "UPDATE tbl_config SET value='$company_name' WHERE config_key='contact_person'";
                        mysqli_query($link, $sql);

                        $sql = "UPDATE tbl_config SET value='$username' WHERE config_key='mail_username'";
                        mysqli_query($link, $sql);

                        $sql = "UPDATE tbl_config SET value='$company_email' WHERE config_key='company_email'";
                        mysqli_query($link, $sql);

                        $sql = "UPDATE tbl_config SET value='$timezone' WHERE config_key='timezone'";
                        mysqli_query($link, $sql);

                        $step = 5;
                    }
                } else {
                    $bug_error = $result['error'];
                }
            } else {
                $bug_error = $bug_error;
            }
        }
        $this->already_installed();
        require_once('html.php');
    }

    public function hash($string, $encryption_key = null)
    {
        if (empty($encryption_key)) {
            $encryption_key = 'b1e7b1e7b1e7b1e7b1e7b1e7b1e7b1e7';
        }
        return hash('sha512', $string . $encryption_key);
    }

    public function install_db($POST, $sql_file)
    {
        $mysqli = $this->connect_db($POST);

        if (!$mysqli || mysqli_connect_errno()) {
            return false;
        }
        $mysqli->multi_query($sql_file);

        do {
        } while (mysqli_more_results($mysqli) && mysqli_next_result($mysqli));
        $mysqli->close();

        return true;
    }

    private function connect_db($post)
    {
        try {
            return @mysqli_connect($post['hostname'], $post['db_username'], $post['db_password'], $post['database']);
        } catch (Throwable $e) {
            return false;
        }
    }

    public function remote_get_contents($post, $getDB = null)
    {
        if (function_exists('curl_init')) {
            return self::curl_get_contents($post, $getDB);
        } else {
            return 'Please enable the curl function';
        }
    }

    public function curl_get_contents($post, $getDB = null)
    {
        if (!empty($getDB)) {
            $url = UPDATE_URL . 'api/getDB';
        } else {
            $url = UPDATE_URL . 'api/check';
        }
        $curl_handle = curl_init();
        curl_setopt($curl_handle, CURLOPT_URL, $url);
        curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl_handle, CURLOPT_POST, 1);
        $path = substr(realpath(dirname(__FILE__)), 0, -8);
        curl_setopt($curl_handle, CURLOPT_POSTFIELDS, array(
            'envato_username' => $post['envato_username'],
            'support_email' => $post['support_email'],
            'purchase_code' => $post['purchase_code'],
            'item_id' => '16292398',
            'ip_address' => isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : $_SERVER["HTTP_HOST"],
            'url' => $this->base_url(), // please do not change the URL this is mandatory to setup the software
            'path' => $path,
        ));
        $output = curl_exec($curl_handle);
        curl_close($curl_handle);
        return $output;
    }

    public function is_localhost()
    {
        $whitelist = array(
            '127.0.0.1',
            '::1'
        );
        if (in_array($_SERVER['REMOTE_ADDR'], $whitelist)) {
            return true;
        }

        return false;
    }

    private function clean_up_db_query($link)
    {
        while (mysqli_more_results($link) && mysqli_next_result($link)) {
            $dummyResult = mysqli_use_result($link);

            if ($dummyResult instanceof mysqli_result) {
                mysqli_free_result($link);
            }
        }
    }

    public function already_installed()
    {
        $output_path = '../application/config/install.php';
        if (!file_exists($output_path)) {
            header('location:../login');
        }
    }

    private function write_app_config($post)
    {

        $template_path = 'config/app-config.php';
        $output_path = '../application/config/app-config.php';
        $install = '../application/config/install.php';

        $config_file = file_get_contents($template_path);
        $replacements = array(
            '%BASE_URL%' => $this->php_string($this->normalize_base_url($post['app_base_url'])),
            '%ENCRYPTION_KEY%' => $this->php_string($post['app_enc_key']),
            'INSTALL_LEGACY_PASSWORD_KEYS' => var_export(array(), true),
            '%HOSTNAME%' => $this->php_string($post['hostname']),
            '%USERNAME%' => $this->php_string($post['db_username']),
            '%PASSWORD%' => $this->php_string($post['db_password']),
            '%DATABASE%' => $this->php_string($post['database']),
            '%CHARSET%' => 'utf8mb4',
            '%COLLATION%' => 'utf8mb4_unicode_ci',
        );

        $new = strtr($config_file, $replacements);

        $handle = fopen($output_path, 'w+');
        if (!$handle) {
            return false;
        }

        @chmod($output_path, 0666);
        if (!is_writable($output_path)) {
            fclose($handle);
            return false;
        }

        $written = fwrite($handle, $new);
        fclose($handle);
        if ($written === false) {
            return false;
        }

        if (file_exists($install)) {
            unlink($install);
        }

        return true;
    }

    private function db_escape($link, $value)
    {
        return mysqli_real_escape_string($link, trim((string)$value));
    }

    private function normalize_base_url($url)
    {
        $url = trim((string)$url);
        return rtrim($url, '/') . '/';
    }

    private function php_string($value)
    {
        return str_replace(array('\\', "'"), array('\\\\', "\\'"), (string)$value);
    }

    public function encryption_key()
    {
        try {
            return bin2hex(random_bytes(16));
        } catch (Exception $e) {
            return md5(uniqid('', true)) . md5(mt_rand());
        }
    }

    public function base_url()
    {
        $base_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ? 'https' : 'http';
        $base_url .= '://' . $_SERVER['HTTP_HOST'];
        $base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
        $base_url = preg_replace('/install.*/', '', $base_url);

        return $base_url;
    }

    public function get_timezones_list()
    {
        $timezoneIdentifiers = DateTimeZone::listIdentifiers();
        $utcTime = new DateTime('now', new DateTimeZone('UTC'));

        $tempTimezones = array();
        foreach ($timezoneIdentifiers as $timezoneIdentifier) {
            $currentTimezone = new DateTimeZone($timezoneIdentifier);

            $tempTimezones[] = array(
                'offset' => (int)$currentTimezone->getOffset($utcTime),
                'identifier' => $timezoneIdentifier
            );
        }

        usort($tempTimezones, function ($a, $b) {
            return ($a['offset'] == $b['offset']) ? strcmp($a['identifier'], $b['identifier']) : $a['offset'] - $b['offset'];
        });

        $timezoneList = array();
        foreach ($tempTimezones as $tz) {
            $sign = ($tz['offset'] > 0) ? '+' : '-';
            $offset = gmdate('H:i', abs($tz['offset']));
            $timezoneList[$tz['identifier']] = '(UTC ' . $sign . $offset . ') ' .
                $tz['identifier'];
        }
        return $timezoneList;
    }
}
