<?php

if (!defined('WPVIVID_PLUGIN_DIR')){
    die;
}

require_once WPVIVID_PLUGIN_DIR . '/includes/customclass/class-wpvivid-remote.php';

if(!defined('WPVIVID_REMOTE_GOOGLEDRIVE'))
    define('WPVIVID_REMOTE_GOOGLEDRIVE','googledrive');
if(!defined('WPVIVID_GOOGLEDRIVE_DEFAULT_FOLDER'))
    define('WPVIVID_GOOGLEDRIVE_DEFAULT_FOLDER','wpvivid_backup');
if(!defined('WPVIVID_GOOGLEDRIVE_SECRETS'))
    define('WPVIVID_GOOGLEDRIVE_SECRETS',WPVIVID_PLUGIN_DIR.'/includes/customclass/client_secrets.json');
if(!defined('WPVIVID_GOOGLEDRIVE_UPLOAD_SIZE'))
    define('WPVIVID_GOOGLEDRIVE_UPLOAD_SIZE',1024*1024*2);
if(!defined('WPVIVID_GOOGLE_NEED_PHP_VERSION'))
    define('WPVIVID_GOOGLE_NEED_PHP_VERSION','5.5');
class Wpvivid_Google_drive extends WPvivid_Remote
{
    public $options;

    public $google_drive_secrets;

    public function __construct($options=array())
    {
        if(empty($options))
        {
            if(!defined('WPVIVID_INIT_STORAGE_TAB_GOOGLE_DRIVE'))
            {
                add_action('init', array($this, 'handle_auth_actions'));

                add_action('wpvivid_add_storage_tab',array($this,'wpvivid_add_storage_tab_google_drive'), 10);
                add_action('wpvivid_add_storage_page',array($this,'wpvivid_add_storage_page_google_drive'), 10);
                add_filter('wpvivid_pre_add_remote',array($this, 'pre_add_remote'),10,2);
                add_action('wpvivid_edit_remote_page',array($this,'wpvivid_edit_storage_page_google_drive'), 10);
                add_filter('wpvivid_remote_pic',array($this,'wpvivid_remote_pic_google_drive'),10);
                add_filter('wpvivid_get_out_of_date_remote',array($this,'wpvivid_get_out_of_date_google_drive'),10,2);
                add_filter('wpvivid_storage_provider_tran',array($this,'wpvivid_storage_provider_google_drive'),10);
                add_filter('wpvivid_get_root_path',array($this,'wpvivid_get_root_path_google_drive'),10);
                define('WPVIVID_INIT_STORAGE_TAB_GOOGLE_DRIVE',1);
            }

        }
        else
        {
            $this->options=$options;
        }
        $this->google_drive_secrets = array("web"=>array(
            "client_id"=>"134809148507-32crusepgace4h6g47ota99jjrvf4j1u.apps.googleusercontent.com",
            "project_id"=>"wpvivid-auth",
            "auth_uri"=>"https://accounts.google.com/o/oauth2/auth",
            "token_uri"=>"https://oauth2.googleapis.com/token",
            "auth_provider_x509_cert_url"=>"https://www.googleapis.com/oauth2/v1/certs",
            "client_secret"=>"GmD5Kmg_1fTcf0ciNEomposy",
            "redirect_uris"=>array("https://auth.wpvivid.com/google_drive_v2/")
        ));
    }

    public function pre_add_remote($remote,$id)
    {
        if($remote['type']==WPVIVID_REMOTE_GOOGLEDRIVE)
        {
            $remote['id']=$id;
        }

        return $remote;
    }

    public function handle_auth_actions()
    {
        if (isset($_GET['action']) && isset($_GET['page']))
        {
            if($_GET['page'] === 'WPvivid')
            {
                if($_GET['action']=='wpvivid_google_drive_auth')
                {
                    if(!isset($_GET['name'])||empty($_GET['name']))
                    {
                        echo '<div class="notice notice-warning is-dismissible"><p>'.__('Warning: An alias for remote storage is required.', 'wpvivid-backuprestore').'</p></div>';
                        return;
                    }

                    $alias_name=sanitize_text_field($_GET['name']);
                    $auth_id = uniqid('wpvivid-auth-');
                    $default = sanitize_text_field($_GET['default']);

                    $remoteslist=WPvivid_Setting::get_all_remote_options();
                    foreach ($remoteslist as $key=>$value)
                    {
                        if(isset($value['name'])&&$value['name'] == $alias_name)
                        {
                            echo '<div class="notice notice-warning is-dismissible"><p>'.__('Warning: The alias already exists in storage list.', 'wpvivid-backuprestore').'</p></div>';
                            return;
                        }
                    }
                    $res = $this -> compare_php_version();
                    if($res['result'] == WPVIVID_FAILED){
                        echo '<div class="notice notice-warning is-dismissible"><p>'.$res['error'].'</p></div>';
                        return ;
                    }
                    try {
                        include_once WPVIVID_PLUGIN_DIR . '/vendor/autoload.php';
                        $client = new Google_Client();
                        $client->setAuthConfig($this->google_drive_secrets);
                        $client->setApprovalPrompt('force');
                        $client->addScope(Google_Service_Drive::DRIVE_FILE);
                        $client->setAccessType('offline');
                        $client->setState(admin_url() . 'admin.php?page=WPvivid' . '&action=wpvivid_google_drive_finish_auth&name=' . $alias_name . '&default=' . $default.'&auth_id='.$auth_id);
                        $auth_url = $client->createAuthUrl();
                        header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
                    }
                    catch (Exception $e){
                        if($e->getMessage() === 'file does not exist'){
                            $error_msg = __('Authentication failed, the client_secrets.json file is missing. Please make sure the client_secrets.json file is in wpvivid-backuprestore\includes\customclass directory.', 'wpvivid-backuprestore');
                            echo '<div class="notice notice-error"><p>'.$error_msg.'</p></div>';
                        }
                        else if($e->getMessage() === 'invalid json for auth config'){
                            $error_msg = __('Authentication failed, the format of the client_secrets.json file is incorrect. Please delete and re-install the plugin to recreate the file.', 'wpvivid-backuprestore');
                            echo '<div class="notice notice-error"><p>'.$error_msg.'</p></div>';
                        }
                        else{
                            echo '<div class="notice notice-error"><p>'.$e->getMessage().'</p></div>';
                        }
                    }
                }
                else if($_GET['action']=='wpvivid_google_drive_finish_auth')
                {
                    file_put_contents('D:\page.txt', json_encode($_GET));
                    try {

                        if(isset($_GET['error']))
                        {
                            header('Location: '.admin_url().'admin.php?page='.WPVIVID_PLUGIN_SLUG.'&action=wpvivid_google_drive&result=error&resp_msg='.sanitize_text_field($_GET['error']));

                            return;
                        }
                        $remoteslist = WPvivid_Setting::get_all_remote_options();
                        foreach ($remoteslist as $key => $value) {
                            if (isset($value['auth_id']) && isset($_GET['auth_id']) && $value['auth_id'] == sanitize_text_field($_GET['auth_id'])) {
                                _e('<div class="notice notice-success is-dismissible"><p>You have authenticated the Google Drive account as your remote storage.</p></div>');
                                return;
                            }
                        }
                        if(isset($_POST) && !empty($_POST) && !isset($_POST['refresh_token']))
                        {
                            $err = 'No refresh token was received from Google, which means that you entered client secret incorrectly, or that you did not re-authenticated yet after you corrected it. Please authenticate again.';
                            header('Location: '.admin_url().'admin.php?page='.WPVIVID_PLUGIN_SLUG.'&action=wpvivid_google_drive&result=error&resp_msg='.$err);

                            return;
                        }

                        global $wpvivid_plugin;

                        $remote_options['type'] = WPVIVID_REMOTE_GOOGLEDRIVE;
                        $remote_options['token']['access_token'] = sanitize_text_field($_POST['access_token']);
                        $remote_options['token']['expires_in'] = sanitize_text_field($_POST['expires_in']);
                        $remote_options['token']['refresh_token'] = sanitize_text_field($_POST['refresh_token']);
                        $remote_options['token']['scope'] = sanitize_text_field($_POST['scope']);
                        $remote_options['token']['token_type'] = sanitize_text_field($_POST['token_type']);
                        $remote_options['token']['created'] = sanitize_text_field($_POST['created']);
                        $remote_options['name'] = sanitize_text_field($_GET['name']);
                        $remote_options['default'] = sanitize_text_field($_GET['default']);
                        $remote_options['path'] = WPVIVID_GOOGLEDRIVE_DEFAULT_FOLDER;
                        $remote_options['auth_id'] = sanitize_text_field($_GET['auth_id']);
                        $ret = $wpvivid_plugin->remote_collection->add_remote($remote_options);

                        if ($ret['result'] == 'success') {
                            header('Location: ' . admin_url() . 'admin.php?page=' . WPVIVID_PLUGIN_SLUG . '&action=wpvivid_google_drive&result=success');
                            return;
                        } else {
                            header('Location: ' . admin_url() . 'admin.php?page=' . WPVIVID_PLUGIN_SLUG . '&action=wpvivid_google_drive&result=error&resp_msg=' . $ret['error']);
                            return;
                        }
                    }
                    catch (Exception $e){
                        echo '<div class="notice notice-error"><p>'.$e->getMessage().'</p></div>';
                    }
                }
                else if($_GET['action']=='wpvivid_google_drive')
                {
                    try {
                        if (isset($_GET['result'])) {
                            if ($_GET['result'] == 'success') {
                                add_action('show_notice', array($this, 'wpvivid_show_notice_add_google_drive_success'));
                            } else if ($_GET['result'] == 'error') {
                                add_action('show_notice', array($this, 'wpvivid_show_notice_add_google_drive_error'));
                            }
                        }
                    }
                    catch (Exception $e){
                        echo '<div class="notice notice-error"><p>'.$e->getMessage().'</p></div>';
                    }
                }
                else if($_GET['action']=='wpvivid_google_drive_update_auth')
                {
                    if(!isset($_GET['name'])||empty($_GET['name']))
                    {
                        echo '<div class="notice notice-warning is-dismissible"><p>'.__('Warning: An alias for remote storage is required.', 'wpvivid-backuprestore').'</p></div>';
                        return;
                    }

                    $alias_name=sanitize_text_field($_GET['name']);
                    $id = sanitize_text_field($_GET['id']);
                    $auth_id = uniqid('wpvivid-auth-');

                    $remoteslist=WPvivid_Setting::get_all_remote_options();
                    foreach ($remoteslist as $key=>$value)
                    {
                        if(isset($value['name'])&&$value['name'] == $alias_name&&$key!=$id)
                        {
                            echo '<div class="notice notice-warning is-dismissible"><p>'.__('Warning: The alias already exists in storage list.', 'wpvivid-backuprestore').'</p></div>';
                            return;
                        }
                    }

                    try {
                        include_once WPVIVID_PLUGIN_DIR . '/vendor/autoload.php';
                        $client = new Google_Client();
                        $client->setAuthConfig($this->google_drive_secrets);
                        $client->setApprovalPrompt('force');
                        $client->addScope(Google_Service_Drive::DRIVE_FILE);
                        $client->setAccessType('offline');
                        $client->setState(admin_url() . 'admin.php?page=WPvivid' . '&action=wpvivid_google_drive_finish_update_auth&name=' . $alias_name . '&id=' . $id.'&auth_id='.$auth_id);
                        $auth_url = $client->createAuthUrl();
                        header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
                    }
                    catch (Exception $e){
                        if($e->getMessage() === 'file does not exist'){
                            $error_msg = __('Authentication failed, the client_secrets.json file is missing. Please make sure the client_secrets.json file is in wpvivid-backuprestore\includes\customclass directory.', 'wpvivid-backuprestore');
                            echo '<div class="notice notice-error"><p>'.$error_msg.'</p></div>';
                        }
                        else if($e->getMessage() === 'invalid json for auth config'){
                            $error_msg = __('Authentication failed, the format of the client_secrets.json file is incorrect. Please delete and re-install the plugin to recreate the file.', 'wpvivid-backuprestore');
                            echo '<div class="notice notice-error"><p>'.$error_msg.'</p></div>';
                        }
                        else{
                            echo '<div class="notice notice-error"><p>'.$e->getMessage().'</p></div>';
                        }
                    }
                }
                else if($_GET['action']=='wpvivid_google_drive_finish_update_auth')
                {
                    try {
                        if(isset($_GET['error']))
                        {
                            header('Location: '.admin_url().'admin.php?page='.WPVIVID_PLUGIN_SLUG.'&action=wpvivid_google_drive_update&result=error&resp_msg='.sanitize_text_field($_GET['error']));

                            return;
                        }
                        $remoteslist = WPvivid_Setting::get_all_remote_options();
                        foreach ($remoteslist as $key => $value) {
                            if (isset($value['auth_id']) && isset($_GET['auth_id']) && $value['auth_id'] == sanitize_text_field($_GET['auth_id'])) {
                                _e('<div class="notice notice-success is-dismissible"><p>You have successfully updated the storage alias.</p></div>');
                                return;
                            }
                        }

                        global $wpvivid_plugin;

                        $remote_options['type'] = WPVIVID_REMOTE_GOOGLEDRIVE;
                        $remote_options['token']['access_token'] = sanitize_text_field($_POST['access_token']);
                        $remote_options['token']['expires_in'] = sanitize_text_field($_POST['expires_in']);
                        $remote_options['token']['refresh_token'] = sanitize_text_field($_POST['refresh_token']);
                        $remote_options['token']['scope'] = sanitize_text_field($_POST['scope']);
                        $remote_options['token']['token_type'] = sanitize_text_field($_POST['token_type']);
                        $remote_options['token']['created'] = sanitize_text_field($_POST['created']);
                        $remote_options['name'] = sanitize_text_field($_GET['name']);
                        $remote_options['path'] = WPVIVID_GOOGLEDRIVE_DEFAULT_FOLDER;
                        $remote_options['auth_id'] = sanitize_text_field($_GET['auth_id']);
                        $ret = $wpvivid_plugin->remote_collection->update_remote($remote_options['auth_id'], $remote_options);

                        if ($ret['result'] == 'success') {
                            header('Location: ' . admin_url() . 'admin.php?page=' . WPVIVID_PLUGIN_SLUG . '&action=wpvivid_google_drive_update&result=success');
                            return;
                        } else {
                            header('Location: ' . admin_url() . 'admin.php?page=' . WPVIVID_PLUGIN_SLUG . '&action=wpvivid_google_drive_update&result=error&resp_msg=' . $ret['error']);
                            return;
                        }
                    }
                    catch (Exception $e){
                        echo '<div class="notice notice-error"><p>'.$e->getMessage().'</p></div>';
                    }
                }
                else if($_GET['action']=='wpvivid_google_drive_update')
                {
                    try {
                        if (isset($_GET['result'])) {
                            if ($_GET['result'] == 'success') {
                                add_action('show_notice', array($this, 'wpvivid_show_notice_edit_google_drive_success'));
                            } else if ($_GET['result'] == 'error') {
                                add_action('show_notice', array($this, 'wpvivid_show_notice_edit_google_drive_error'));
                            }
                        }
                    }
                    catch (Exception $e){
                        echo '<div class="notice notice-error"><p>'.$e->getMessage().'</p></div>';
                    }
                }
            }
        }
    }
    public function wpvivid_show_notice_add_google_drive_success(){
        echo '<div class="notice notice-success is-dismissible"><p>'.__('You have authenticated the Google Drive account as your remote storage.', 'wpvivid-backuprestore').'</p></div>';
    }
    public function wpvivid_show_notice_add_google_drive_error(){
        global $wpvivid_plugin;
        $wpvivid_plugin->wpvivid_handle_remote_storage_error($_GET['resp_msg'], 'Add Google Drive Remote');
        echo '<div class="notice notice-error"><p>'.esc_html($_GET['resp_msg']).'</p></div>';
    }
    public function wpvivid_show_notice_edit_google_drive_success(){
        echo '<div class="notice notice-success is-dismissible"><p>'.__('You have successfully updated the storage alias.', 'wpvivid-backuprestore').'</p></div>';
    }
    public function wpvivid_show_notice_edit_google_drive_error(){
        global $wpvivid_plugin;
        $wpvivid_plugin->wpvivid_handle_remote_storage_error($_GET['resp_msg'], 'Update Google Drive Remote');
        echo '<div class="notice notice-error"><p>'.esc_html($_GET['resp_msg']).'</p></div>';
    }

    public function wpvivid_add_storage_tab_google_drive()
    {
        ?>
        <div class="storage-providers storage-providers-active" remote_type="googledrive" onclick="select_remote_storage(event, 'storage_account_google_drive');">
            <img src="<?php echo esc_url(WPVIVID_PLUGIN_URL.'/admin/partials/images/stroage-google-drive.png'); ?>" style="vertical-align:middle;"/><?php _e('Google Drive', 'wpvivid-backuprestore'); ?>
        </div>
        <?php
    }

    public function wpvivid_add_storage_page_google_drive()
    {
        global $wpvivid_plugin;
        $root_path=apply_filters('wpvivid_get_root_path', WPVIVID_REMOTE_GOOGLEDRIVE);
        ?>
        <div id="storage_account_google_drive" class="storage-account-page">
            <div style="background-color:#f1f1f1; padding: 10px;">
                <?php _e('Please read <a target="_blank" href="https://wpvivid.com/privacy-policy" style="text-decoration: none;">this privacy policy</a> for use of our Google Drive authorization app (none of your backup data is sent to us).', 'wpvivid-backuprestore'); ?>
            </div>
            <div style="padding: 10px 10px 10px 0;">
                <strong><?php _e('Enter Your Google Drive Information', 'wpvivid-backuprestore'); ?></strong>
            </div>
            <table class="wp-list-table widefat plugins" style="width:100%;">
                <tbody>
                <tr>
                    <td class="plugin-title column-primary">
                        <div class="wpvivid-storage-form">
                            <input type="text" class="regular-text" autocomplete="off" option="googledrive" name="name" placeholder="<?php esc_attr_e('Enter a unique alias: e.g. Google Drive-001', 'wpvivid-backuprestore'); ?>" onkeyup="value=value.replace(/[^a-zA-Z0-9\-_]/g,'')" />
                        </div>
                    </td>
                    <td class="column-description desc">
                        <div class="wpvivid-storage-form-desc">
                            <i><?php _e('A name to help you identify the storage if you have multiple remote storage connected.', 'wpvivid-backuprestore'); ?></i>
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="plugin-title column-primary">
                        <div class="wpvivid-storage-form">
                            <input type="text" class="regular-text" autocomplete="off" option="googledrive" name="path" value="<?php esc_attr_e($root_path.WPVIVID_GOOGLEDRIVE_DEFAULT_FOLDER); ?>" readonly="readonly" />
                        </div>
                    </td>
                    <td class="column-description desc">
                        <div class="wpvivid-storage-form-desc">
                            <i><?php _e('All backups will be uploaded to this directory.', 'wpvivid-backuprestore'); ?></i>
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="plugin-title column-primary">
                        <div class="wpvivid-storage-form">
                            <input type="text" class="regular-text" autocomplete="off" value="mywebsite01" readonly="readonly" />
                        </div>
                    </td>
                    <td class="column-description desc">
                        <div class="wpvivid-storage-form-desc">
                            <a href="https://docs.wpvivid.com/wpvivid-backup-pro-google-drive-custom-folder-name.html"><?php _e('Pro feature: Create a directory for storing the backups of the site', 'wpvivid-backuprestore'); ?></a>
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="plugin-title column-primary">
                        <div class="wpvivid-storage-select">
                            <label>
                                <input type="checkbox" option="googledrive" name="default" checked /><?php _e('Set as the default remote storage.', 'wpvivid-backuprestore'); ?>
                            </label>
                        </div>
                    </td>
                    <td class="column-description desc">
                        <div class="wpvivid-storage-form-desc">
                            <i><?php _e('Once checked, all this sites backups sent to a remote storage destination will be uploaded to this storage by default.', 'wpvivid-backuprestore'); ?></i>
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="plugin-title column-primary">
                        <div class="wpvivid-storage-form">
                            <input onclick="wpvivid_google_drive_auth();" class="button-primary" type="submit" value="<?php esc_attr_e('Authenticate with Google Drive', 'wpvivid-backuprestore'); ?>" />
                        </div>
                    </td>
                    <td class="column-description desc">
                        <div class="wpvivid-storage-form-desc">
                            <i><?php _e('Click the button to get Google authentication and add it to the storage list below.', 'wpvivid-backuprestore'); ?></i>
                        </div>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <script>
            function wpvivid_check_google_drive_storage_alias(storage_alias){
                var find = 1;
                jQuery('#wpvivid_remote_storage_list tr').each(function (i) {
                    jQuery(this).children('td').each(function (j) {
                        if (j == 3) {
                            if (jQuery(this).text() == storage_alias) {
                                find = -1;
                                return false;
                            }
                        }
                    });
                });
                return find;
            }
            function wpvivid_google_drive_auth()
            {
                wpvivid_settings_changed = false;
                var name='';
                var path='';
                jQuery('input:text[option=googledrive]').each(function()
                {
                    var key = jQuery(this).prop('name');
                    if(key==='name')
                    {
                        name = jQuery(this).val();
                    }
                });

                var remote_default='0';

                jQuery('input:checkbox[option=googledrive]').each(function()
                {
                    if(jQuery(this).prop('checked')) {
                        remote_default='1';
                    }
                    else {
                        remote_default='0';
                    }
                });
                if(name == ''){
                    alert(wpvividlion.remotealias);
                }
                else if(wpvivid_check_google_drive_storage_alias(name) === -1){
                    alert(wpvividlion.remoteexist);
                }
                else {
                    location.href = '<?php echo admin_url() . 'admin.php?page=WPvivid' . '&action=wpvivid_google_drive_auth&name='?>' + name + '&default=' + remote_default;
                }
            }
        </script>
        <?php
    }

    public function wpvivid_edit_storage_page_google_drive()
    {
        ?>
        <div id="remote_storage_edit_googledrive" class="postbox storage-account-block remote-storage-edit" style="display:none;">
            <div style="padding: 0 10px 10px 0;">
                <strong><?php _e('Enter Your Google Drive Information', 'wpvivid-backuprestore'); ?></strong>
            </div>
            <table class="wp-list-table widefat plugins" style="width:100%;">
                <tbody>
                <tr>
                    <td class="plugin-title column-primary">
                        <div class="wpvivid-storage-form">
                            <input type="text" class="regular-text" autocomplete="off" option="edit-googledrive" name="name" placeholder="<?php esc_attr_e('Enter a unique alias: e.g. Google Drive-001', 'wpvivid-backuprestore'); ?>" onkeyup="value=value.replace(/[^a-zA-Z0-9\-_]/g,'')" />
                        </div>
                    </td>
                    <td class="column-description desc">
                        <div class="wpvivid-storage-form-desc">
                            <i><?php _e('A name to help you identify the storage if you have multiple remote storage connected.', 'wpvivid-backuprestore'); ?></i>
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="plugin-title column-primary">
                        <div class="wpvivid-storage-form">
                            <input onclick="wpvivid_google_drive_update_auth();" class="button-primary" type="submit" value="<?php esc_attr_e('Save Changes', 'wpvivid-backuprestore'); ?>" />
                        </div>
                    </td>
                    <td class="column-description desc">
                        <div class="wpvivid-storage-form-desc">
                            <i><?php _e('Click the button to save the changes.', 'wpvivid-backuprestore');?></i>
                        </div>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <script>
            function wpvivid_google_drive_update_auth()
            {
                var name='';
                jQuery('input:text[option=edit-googledrive]').each(function()
                {
                    var key = jQuery(this).prop('name');
                    if(key==='name')
                    {
                        name = jQuery(this).val();
                    }
                });

                if(name == ''){
                    alert(wpvividlion.remotealias);
                }
                else if(wpvivid_check_onedrive_storage_alias(name) === -1){
                    alert(wpvividlion.remoteexist);
                }
                else {
                    location.href = '<?php echo admin_url() . 'admin.php?page=WPvivid' . '&action=wpvivid_google_drive_update_auth&name='?>' + name + '&id=' + wpvivid_editing_storage_id;
                }
            }
        </script>
        <?php
    }

    public function wpvivid_remote_pic_google_drive($remote)
    {
        $remote['googledrive']['default_pic'] = '/admin/partials/images/stroage-google-drive(gray).png';
        $remote['googledrive']['selected_pic'] = '/admin/partials/images/stroage-google-drive.png';
        $remote['googledrive']['title'] = 'Google Drive';
        return $remote;
    }

    public function sanitize_options($skip_name='')
    {
        $ret['result']=WPVIVID_SUCCESS;

        if(!isset($this->options['name']))
        {
            $ret['error']="Warning: An alias for remote storage is required.";
            return $ret;
        }

        $this->options['name']=sanitize_text_field($this->options['name']);

        if(empty($this->options['name']))
        {
            $ret['error']="Warning: An alias for remote storage is required.";
            return $ret;
        }

        $remoteslist=WPvivid_Setting::get_all_remote_options();
        foreach ($remoteslist as $key=>$value)
        {
            if(isset($value['name'])&&$value['name'] == $this->options['name']&&$skip_name!=$value['name'])
            {
                $ret['error']="Warning: The alias already exists in storage list.";
                return $ret;
            }
        }

        $ret['options']=$this->options;
        return $ret;
    }

    public function test_connect()
    {
        return array('result' => WPVIVID_SUCCESS);
    }

    public function upload($task_id, $files, $callback = '')
    {
        global $wpvivid_plugin;


        $client=$this->get_client();
        if($client['result'] == WPVIVID_FAILED){
            return $client;
        }
        $client = $client['data'];

        if($client===false)
        {
            return array('result' => WPVIVID_FAILED,'error'=> 'Token refresh failed.');
        }

        $service = new Google_Service_Drive($client);
        $path=$this->options['path'];
        $wpvivid_plugin->wpvivid_log->WriteLog('Check upload folder '.$path,'notice');
        $folder_id=$this->get_folder($service,$path);

        if($folder_id==false)
        {
            return array('result' => WPVIVID_FAILED,'error'=> 'Unable to create the local file. Please make sure the folder is writable and try again.');
        }

        $upload_job=WPvivid_taskmanager::get_backup_sub_task_progress($task_id,'upload',WPVIVID_REMOTE_GOOGLEDRIVE);
        if(empty($upload_job))
        {
            $job_data=array();
            foreach ($files as $file)
            {
                $file_data['size']=filesize($file);
                $file_data['uploaded']=0;
                $job_data[basename($file)]=$file_data;
            }
            WPvivid_taskmanager::update_backup_sub_task_progress($task_id,'upload',WPVIVID_REMOTE_GOOGLEDRIVE,WPVIVID_UPLOAD_UNDO,'Start uploading',$job_data);
            $upload_job=WPvivid_taskmanager::get_backup_sub_task_progress($task_id,'upload',WPVIVID_REMOTE_GOOGLEDRIVE);
        }

        foreach ($files as $file)
        {
            if(is_array($upload_job['job_data'])&&array_key_exists(basename($file),$upload_job['job_data']))
            {
                if($upload_job['job_data'][basename($file)]['uploaded']==1)
                    continue;
            }

            $this -> last_time = time();
            $this -> last_size = 0;

            if(!file_exists($file))
                return array('result' =>WPVIVID_FAILED,'error' =>$file.' not found. The file might has been moved, renamed or deleted. Please reload the list and verify the file exists.');
            $wpvivid_plugin->wpvivid_log->WriteLog('Start uploading '.basename($file),'notice');
            $wpvivid_plugin->set_time_limit($task_id);
            $result=$this->_upload($task_id, $file,$client,$service,$folder_id, $callback);
            if($result['result'] !==WPVIVID_SUCCESS){
                return $result;
            }

            $ref=$this->check_token($client);
            if($ref['result']=!WPVIVID_SUCCESS)
            {
                return $ref;
            }
        }
        return array('result' =>WPVIVID_SUCCESS);
    }

    public function check_token(&$client)
    {
        if ($client->isAccessTokenExpired())
        {
            // Refresh the token if possible, else fetch a new one.
            global $wpvivid_plugin;
            $wpvivid_plugin->wpvivid_log->WriteLog('Refresh the token.','notice');
            if ($client->getRefreshToken())
            {
                $tmp_refresh_token = $client->getRefreshToken();
                $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                $token=$client->getAccessToken();
                $remote_options=WPvivid_Setting::get_remote_option($this->options['id']);
                $this->options['token']=json_decode(json_encode($token),1);
                if($remote_options!==false)
                {
                    if(!isset($this->options['token']['refresh_token'])){
                        $this->options['token']['refresh_token'] = $tmp_refresh_token;
                    }
                    $remote_options['token']=$this->options['token'];
                    WPvivid_Setting::update_remote_option($this->options['id'],$remote_options);
                }
                return array('result' => WPVIVID_SUCCESS);
            }
            else
            {
                return array('result' => WPVIVID_FAILED,'error'=>'get refresh token failed');
            }
        }
        else
        {
            return array('result' => WPVIVID_SUCCESS);
        }
    }

    public function _upload($task_id, $file,$client,$service,$folder_id, $callback = '')
    {
        global $wpvivid_plugin;
        $wpvivid_plugin->wpvivid_log->WriteLog('Check if the server already has the same name file.','notice');
        if(!$this->delete_exist_file($folder_id,basename($file),$service))
        {
            return array('result' =>WPVIVID_FAILED,'error'=>'Uploading '.$file.' to Google Drive server failed. '.$file.' might be deleted or network doesn\'t work properly . Please verify the file and confirm the network connection and try again later.');
        }

        $upload_job=WPvivid_taskmanager::get_backup_sub_task_progress($task_id,'upload',WPVIVID_REMOTE_GOOGLEDRIVE);
        $this -> current_file_size = filesize($file);
        $this -> current_file_name = basename($file);

        $wpvivid_plugin->wpvivid_log->WriteLog('Initiate a resumable upload session.','notice');
        $fileMetadata = new Google_Service_Drive_DriveFile(array(
            'name' => basename($file),
            'parents' => array($folder_id)));
        $chunk_size = 1 * 1024 * 1024;
        $client->setDefer(true);
        $request = $service->files->create($fileMetadata);
        $media = new Google_Http_MediaFileUpload(
            $client,
            $request,
            'text/plain',
            null,
            true,
            $chunk_size
        );
        $media->setFileSize(filesize($file));
        $status = false;
        $handle = fopen($file, "rb");

        WPvivid_taskmanager::update_backup_sub_task_progress($task_id,'upload',WPVIVID_REMOTE_GOOGLEDRIVE,WPVIVID_UPLOAD_UNDO,'Start uploading '.basename($file).'.',$upload_job['job_data']);

        $offset=0;

        while (!$status && !feof($handle))
        {
            $chunk = fread($handle, $chunk_size);

            $status = $media->nextChunk($chunk);

            $offset+=strlen($chunk);

            if((time() - $this -> last_time) >3)
            {
                if(is_callable($callback))
                {
                    call_user_func_array($callback,array($offset,$this -> current_file_name,
                        $this->current_file_size,$this -> last_time,$this -> last_size));
                }
                $this -> last_size = $offset;
                $this -> last_time = time();
            }
        }

        fclose($handle);
        $client->setDefer(false);
        if ($status != false)
        {
            $wpvivid_plugin->wpvivid_log->WriteLog('Finished uploading '.basename($file),'notice');
            $upload_job['job_data'][basename($file)]['uploaded']=1;
            WPvivid_taskmanager::update_backup_sub_task_progress($task_id,'upload',WPVIVID_REMOTE_GOOGLEDRIVE,WPVIVID_UPLOAD_SUCCESS,'Uploading '.basename($file).' completed.',$upload_job['job_data']);
            return array('result' =>WPVIVID_SUCCESS);
        }
        else
        {
            return array('result' =>WPVIVID_FAILED,'error'=>'Uploading '.$file.' to Google Drive server failed. '.$file.' might be deleted or network doesn\'t work properly. Please verify the file and confirm the network connection and try again later.');
        }
    }

    private function get_client()
    {
        $res = $this -> compare_php_version();
        if($res['result'] == WPVIVID_FAILED){
            return $res;
        }

        include_once WPVIVID_PLUGIN_DIR.'/vendor/autoload.php';
        $client = new Google_Client();
        $client->setConfig('access_type','offline');
        $client->setAuthConfig($this->google_drive_secrets);
        $client->addScope(Google_Service_Drive::DRIVE_FILE);//
        $client->setAccessToken($this->options['token']);

        if ($client->isAccessTokenExpired())
        {
            // Refresh the token if possible, else fetch a new one.
            if ($client->getRefreshToken())
            {
                $tmp_refresh_token = $client->getRefreshToken();
                $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                $token=$client->getAccessToken();
                $this->options['token']=json_decode(json_encode($token),1);
                if(!isset($this->options['token']['refresh_token'])){
                    $this->options['token']['refresh_token'] = $tmp_refresh_token;
                }
                WPvivid_Setting::update_remote_option($this->options['id'],$this->options);
                return array('result' => WPVIVID_SUCCESS,'data' => $client);
            }
            else
            {
                return array('result' => WPVIVID_SUCCESS,'data' => false);
            }
        }
        else
        {
            return array('result' => WPVIVID_SUCCESS,'data' => $client);
        }
    }

    private function get_folder($service,$path)
    {
        $response = $service->files->listFiles(array(
            'q' => "name ='".$path."' and 'root' in parents and mimeType = 'application/vnd.google-apps.folder'",
            'fields' => 'nextPageToken, files(id, name,mimeType)',
        ));
        if(sizeof($response->getFiles())==0)
        {
            $fileMetadata = new Google_Service_Drive_DriveFile(array(
                'name' => $path,
                'mimeType' => 'application/vnd.google-apps.folder'));
            $file = $service->files->create($fileMetadata, array(
                'fields' => 'id'));

            return $file->id;
        }
        else
        {
            foreach ($response->getFiles() as $file)
            {
                return $file->getId();
            }
        }

        return false;
    }

    public function set_token()
    {
        $remote_options=WPvivid_Setting::get_remote_option($this->options['id']);
        if($remote_options!==false)
        {
            $this->options['token']=$remote_options['token'];
        }
    }

    public function download( $file, $local_path, $callback = '')
    {
        try
        {
            global $wpvivid_plugin;
            $this -> current_file_name = $file['file_name'];
            $this -> current_file_size = $file['size'];
            $this->set_token();
            $wpvivid_plugin->wpvivid_download_log->WriteLog('Google Drive get client.','notice');
            $client=$this->get_client();
            if($client['result'] == WPVIVID_FAILED) {
                return $client;
            }
            $client = $client['data'];

            if($client===false)
            {
                return array('result' => WPVIVID_FAILED,'error'=> 'Token refresh failed.');
            }

            $service = new Google_Service_Drive($client);

            $path=$this->options['path'];
            $wpvivid_plugin->wpvivid_download_log->WriteLog('Create local file.','notice');
            $folder_id=$this->get_folder($service,$path);

            if($folder_id==false)
            {
                return array('result' => WPVIVID_FAILED,'error'=> 'Unable to create the local file. Please make sure the folder is writable and try again.');
            }

            $response = $service->files->listFiles(array(
                'q' => "name='".$file['file_name']."' and '".$folder_id."' in parents",
                'fields' => 'files(id,size,webContentLink)'
            ));

            if(sizeof($response->getFiles())==0)
            {
                return array('result' => WPVIVID_FAILED,'error'=> 'Downloading file failed. The file might be deleted or network doesn\'t work properly. Please verify the file and confirm the network connection and try again later.');
            }
            else
            {
                $fileSize=$file['size'];
                $file_id='';
                foreach ($response->getFiles() as $file)
                {
                    $file_id=$file->getId();
                    break;
                }
                $wpvivid_plugin->wpvivid_download_log->WriteLog('Get download url.','notice');
                $download_url=$this->get_download_url($client,$file_id);

                if(!empty($file_id)||!empty($download_url))
                {
                    $file_path = trailingslashit($local_path).$this -> current_file_name;

                    if(file_exists($file_path))
                    {
                        $offset = filesize($file_path);
                    }
                    else
                    {
                        $offset=0;
                    }

                    $fh = fopen($file_path, 'a');
                    $upload_size = WPVIVID_GOOGLEDRIVE_UPLOAD_SIZE;
                    $http = $client->authorize();
                    $wpvivid_plugin->wpvivid_download_log->WriteLog('Downloading file ' . $file['file_name'] . ', Size: ' . $file['size'] ,'notice');
                    while ($offset < $fileSize)
                    {
                        $upload_end=min($offset+$upload_size-1,$fileSize-1);

                        if ($offset > 0)
                        {
                            $options['headers']['Range']='bytes='.$offset.'-'.$upload_end;
                        } else {
                            $options['headers']['Range']='bytes=0-'.$upload_end;
                        }
                        $request = new WPvividGuzzleHttp\Psr7\Request('GET', $download_url,$options['headers']);
                        $http_request = $http->send($request);
                        $http_response=$http_request->getStatusCode();
                        if (200 == $http_response || 206 == $http_response)
                        {
                            fwrite($fh, $http_request->getBody()->getContents(),$upload_size);
                            $offset=$upload_end + 1;
                        }
                        else
                        {
                            throw new Exception('Failed to obtain any new data at size: '.$offset.' http code:'.$http_response);
                        }

                        if((time() - $this -> last_time) >3)
                        {
                            if(is_callable($callback))
                            {
                                call_user_func_array($callback,array($offset,$this -> current_file_name,
                                    $this->current_file_size,$this -> last_time,$this -> last_size));
                            }
                            $this -> last_size = $offset;
                            $this -> last_time = time();
                        }
                    }
                    fclose($fh);
                }
                else
                {
                    return array('result' => WPVIVID_FAILED,'error'=> 'Downloading file failed. The file might be deleted or network doesn\'t work properly. Please verify the file and confirm the network connection and try again later.');
                }
            }
        }catch(Exception $e)
        {
            return array('result' => WPVIVID_FAILED,'error' => $e -> getMessage());
        }
        return array('result' => WPVIVID_SUCCESS);
    }

    public function get_download_url($client,$file_id)
    {
        $http = $client->authorize();
        $url='https://www.googleapis.com/drive/v2/files/'.$file_id;
        $request = new WPvividGuzzleHttp\Psr7\Request('GET', $url);
        $http_request = $http->send($request);

        $http_response=$http_request->getStatusCode();
        if (200 == $http_response)
        {
            $json=$http_request->getBody()->getContents();
            $json=json_decode($json,1);
            $download_url=$json['downloadUrl'];
            return $download_url;
        }
        else
        {
            throw new Exception('Failed to use v2 api');
        }
    }

    public function delete_exist_file($folder_id,$file,$service)
    {
        $client=$this->get_client();
        if($client['result'] == WPVIVID_FAILED)
            return false;
        $client = $client['data'];

        if($client===false)
        {
            return false;
        }

        $delete_files = $service->files->listFiles(array(
            'q' => "name='".$file."' and '".$folder_id."' in parents",
            'fields' => 'nextPageToken, files(id, name,mimeType)',
        ));

        if(sizeof($delete_files->getFiles())==0)
        {
            return true;
        }
        else
        {
            foreach ($delete_files->getFiles() as $file_google_drive)
            {
                $file_id=$file_google_drive->getId();
                $service->files->delete($file_id);
                return true;
            }
        }

        return false;
    }

    public function cleanup($files)
    {
        $client=$this->get_client();
        if($client['result'] == WPVIVID_FAILED)
            return $client;
        $client = $client['data'];

        if($client===false)
        {
            return array('result' => WPVIVID_FAILED,'error'=> 'Token refresh failed.');
        }

        $service = new Google_Service_Drive($client);

        $path=$this->options['path'];
        $folder_id=$this->get_folder($service,$path);

        if($folder_id==false)
        {
            return array('result' => WPVIVID_FAILED,'error'=> 'Unable to create the local file. Please make sure the folder is writable and try again.');
        }

        foreach ($files as $file)
        {
            $delete_files = $service->files->listFiles(array(
                'q' => "name='".$file."' and '".$folder_id."' in parents",
                'fields' => 'nextPageToken, files(id, name,mimeType)',
            ));

            if(sizeof($delete_files->getFiles())==0)
            {
                continue;
            }
            else
            {
                foreach ($delete_files->getFiles() as $file_google_drive)
                {
                    $file_id=$file_google_drive->getId();
                    $service->files->delete($file_id);
                }
            }
        }
        return array('result' =>WPVIVID_SUCCESS);
    }

    public function wpvivid_get_out_of_date_google_drive($out_of_date_remote, $remote)
    {
        if($remote['type'] == WPVIVID_REMOTE_GOOGLEDRIVE){
            $root_path=apply_filters('wpvivid_get_root_path', $remote['type']);
            $out_of_date_remote = $root_path.$remote['path'];
        }
        return $out_of_date_remote;
    }

    public function wpvivid_storage_provider_google_drive($storage_type)
    {
        if($storage_type == WPVIVID_REMOTE_GOOGLEDRIVE){
            $storage_type = 'Google Drive';
        }
        return $storage_type;
    }

    public function wpvivid_get_root_path_google_drive($storage_type){
        if($storage_type == WPVIVID_REMOTE_GOOGLEDRIVE){
            $storage_type = 'root/';
        }
        return $storage_type;
    }
    private function compare_php_version(){
        if(version_compare(WPVIVID_GOOGLE_NEED_PHP_VERSION,phpversion()) > 0){
            return array('result' => WPVIVID_FAILED,error => 'The required PHP version is higher than '.WPVIVID_GOOGLE_NEED_PHP_VERSION.'. After updating your PHP version, please try again.');
        }
        return array('result' => WPVIVID_SUCCESS);
    }
}