<?php

if (!defined('ABSPATH'))
    exit;

include_once(plugin_dir_path(__FILE__) . 'vendor/autoload.php');

class CF7GSC_googlesheet
{

    private $token;
    private $spreadsheet;
    private $worksheet;
    private static $instance;

    public function __construct()
    {

    }

    public static function setInstance(Google_Client $instance = null)
    {
        self::$instance = $instance;
    }

    public static function getInstance()
    {
        if (is_null(self::$instance)) {
            throw new LogicException("Invalid Client");
        }

        return self::$instance;
    }

    //constructed on call
    public static function preauth($access_code)
    {
        // Fetch API creds
        if (is_multisite()) {
            // Fetch API creds
            $api_creds = get_site_option('cf7gsc_free_api_creds');
        } else {
            // Fetch API creds
            $api_creds = get_option('cf7gsc_free_api_creds');
        }

        $newClientSecret = get_option('is_new_client_secret_cf7gscfree');
        $clientId = ($newClientSecret == 1) ? $api_creds['client_id_web'] : $api_creds['client_id_desk'];
        $clientSecret = ($newClientSecret == 1) ? $api_creds['client_secret_web'] : $api_creds['client_secret_desk'];

        $client = new Google_Client();
        $client->setClientId($clientId);
        $client->setClientSecret($clientSecret);
        $client->setRedirectUri('https://oauth.gsheetconnector.com/auth-api.php');
        $client->setScopes(Google_Service_Sheets::SPREADSHEETS);
        // $client->setScopes(Google_Service_Drive::DRIVE_METADATA_READONLY);
        $client->addScope( Google_Service_Drive::DRIVE_FILE );
        $client->setScopes(Google_Service_Oauth2::USERINFO_EMAIL);
        $client->setAccessType('offline');
        $client->fetchAccessTokenWithAuthCode($access_code);
        $tokenData = $client->getAccessToken();

        CF7GSC_googlesheet::updateToken($tokenData);
    }

    public static function updateToken($tokenData)
    {
        $expires_in = isset($tokenData['expires_in']) ? intval($tokenData['expires_in']) : 0;
        $tokenData['expire'] = time() + $expires_in;
        try {
            if (isset($tokenData['scope'])) {
                $permission = explode(" ", $tokenData['scope']);
               if ( ( in_array("https://www.googleapis.com/auth/drive.metadata.readonly",$permission ) || in_array( 'https://www.googleapis.com/auth/drive.file', $permission ) ) && ( in_array( 'https://www.googleapis.com/auth/spreadsheets', $permission ) ) ) {
                    update_option('gs_verify', 'valid');
                } else {
                update_option('gs_verify', 'invalid-auth');
                }
            }
            $tokenJson = json_encode($tokenData);
            update_option('gs_token', $tokenJson);
        } catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log("Token write fail! - " . $e->getMessage());
        }
    }

    public function auth()
    {
        $tokenData = json_decode(get_option('gs_token'), true);
        if (!isset($tokenData['refresh_token']) || empty($tokenData['refresh_token'])) {
            throw new LogicException("Auth, Invalid OAuth2 access token");
            exit();
        }

        try {
            if (is_multisite()) {
                // Fetch API creds
                $api_creds = get_site_option('cf7gsc_free_api_creds');
            } else {
                // Fetch API creds
                $api_creds = get_option('cf7gsc_free_api_creds');
            }

            $newClientSecret = get_option('is_new_client_secret_cf7gscfree');
            $clientId = ($newClientSecret == 1) ? $api_creds['client_id_web'] : $api_creds['client_id_desk'];
            $clientSecret = ($newClientSecret == 1) ? $api_creds['client_secret_web'] : $api_creds['client_secret_desk'];

            $client = new Google_Client();
            $client->setClientId($clientId);
            $client->setClientSecret($clientSecret);

            // $client->setScopes(Google_Service_Sheets::SPREADSHEETS);
            // $client->setScopes(Google_Service_Drive::DRIVE_METADATA_READONLY);
            // $client->setScopes(Google_Service_Oauth2::USERINFO_EMAIL);
            $client->setScopes([Google_Service_Sheets::SPREADSHEETS, Google_Service_Drive::DRIVE_FILE]);
            $client->refreshToken($tokenData['refresh_token']);
            $client->setAccessType('offline');
            CF7GSC_googlesheet::updateToken($tokenData);

            self::setInstance($client);
        } catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log( $e->getMessage() );
            throw new LogicException("Auth, Error fetching OAuth2 access token, message: " . $e->getMessage());
            exit();
        }
    }

    public function get_user_data()
    {
        $client = self::getInstance();

        $results = $this->get_spreadsheets();

        echo '<pre>';
        print_r($results);
        echo '</pre>';
        $spreadsheets = $this->get_worktabs('1mRuDMnZveDFQrmzHM9s5YkPA4F_dZkHJ1Gh81BvYB2k');
        echo '<pre>';
        print_r($spreadsheets);
        echo '</pre>';
        $this->setSpreadsheetId('1mRuDMnZveDFQrmzHM9s5YkPA4F_dZkHJ1Gh81BvYB2k');
        $this->setWorkTabId('Foglio1');
        $worksheetTab = $this->list_rows();
        echo '<pre>';
        print_r($worksheetTab);
        echo '</pre>';
    }

    //preg_match is a key of error handle in this case
    public function setSpreadsheetId($id)
    {
        $this->spreadsheet = $id;
    }

    public function getSpreadsheetId()
    {

        return $this->spreadsheet;
    }

    public function setWorkTabId($id)
    {
        $this->worksheet = $id;
    }

    public function getWorkTabId()
    {
        return $this->worksheet;
    }

    public function add_row($data)
    {
        try {
            $client = self::getInstance();
            $service = new Google_Service_Sheets($client);
            $spreadsheetId = $this->getSpreadsheetId();
            $work_sheets = $service->spreadsheets->get($spreadsheetId);

            if (!empty($work_sheets) && !empty($data)) {
                foreach ($work_sheets as $sheet) {
                    $properties = $sheet->getProperties();
                    $sheet_id = $properties->getSheetId();

                    $worksheet_id = $this->getWorkTabId();

                    if ($sheet_id == $worksheet_id) {
                        $worksheet_id = $properties->getTitle();
                        $worksheetCell = $service->spreadsheets_values->get($spreadsheetId, $worksheet_id . "!1:1");
                        $insert_data = array();
                        if (isset($worksheetCell->values[0])) {
                            foreach ($worksheetCell->values[0] as $k => $name) {
                                if (isset($data[$name]) && $data[$name] != '') {
                                    $insert_data[] = $data[$name];
                                } else {
                                    $insert_data[] = '';
                                }
                            }
                        }

                        /* RASHID */
                        $tab_name = $worksheet_id;
                        $full_range = $tab_name . "!A1:Z";
                        $response = $service->spreadsheets_values->get($spreadsheetId, $full_range);
                        $get_values = $response->getValues();

                        if ($get_values) {
                            $row = count($get_values) + 1;
                        } else {
                            $row = 1;
                        }
                        $range = $tab_name . "!A" . $row . ":Z";

                        $range_new = $worksheet_id;

                        // Create the value range Object
                        $valueRange = new Google_Service_Sheets_ValueRange();

                        // set values of inserted data
                        $valueRange->setValues(["values" => $insert_data]);

                        // Add two values
                        // Then you need to add configuration
                        //$conf = ["valueInputOption" => "USER_ENTERED"];
                        $conf = ["valueInputOption" => "USER_ENTERED"];

                        // append the spreadsheet(add new row in the sheet)
                        $result = $service->spreadsheets_values->append($spreadsheetId, $range, $valueRange, $conf);
                    }
                }
            }
        } catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log( $e->getMessage() );
            return null;
            exit();
        }
    }

    public function add_multiple_row($data)
    {
        try {
            $client = self::getInstance();
            $service = new Google_Service_Sheets($client);
            $spreadsheetId = $this->getSpreadsheetId();
            $work_sheets = $service->spreadsheets->get($spreadsheetId);

            if (!empty($work_sheets) && !empty($data)) {
                foreach ($work_sheets as $sheet) {
                    $properties = $sheet->getProperties();
                    $sheet_id = $properties->getSheetId();

                    $worksheet_id = $this->getWorkTabId();

                    if ($sheet_id == $worksheet_id) {
                        $worksheet_id = $properties->getTitle();
                        $worksheetCell = $service->spreadsheets_values->get($spreadsheetId, $worksheet_id . "!1:1");
                        $insert_data = array();
                        $final_data = array();
                        if (isset($worksheetCell->values[0])) {
                            foreach ($data as $key => $value) {
                                foreach ($worksheetCell->values[0] as $k => $name) {
                                    if (isset($value[$name]) && $value[$name] != '') {
                                        $insert_data[] = $value[$name];
                                    } else {
                                        $insert_data[] = '';
                                    }
                                }
                                $final_data[] = $insert_data;
                                unset($insert_data);
                            }
                        }

                        //$range_new = $worksheet_id;

                        /* RASHID */
                        $tab_name = $worksheet_id;
                        $full_range = $tab_name . "!A1:Z";
                        $response = $service->spreadsheets_values->get($spreadsheetId, $full_range);
                        $get_values = $response->getValues();

                        if ($get_values) {
                            $row = count($get_values) + 1;
                        } else {
                            $row = 1;
                        }
                        $range = $tab_name . "!A" . $row . ":Z";

                        $sheet_values = $final_data;

                        if (!empty($sheet_values)) {
                            $requestBody = new Google_Service_Sheets_ValueRange([
                                'values' => $sheet_values
                            ]);

                            $params = [
                                'valueInputOption' => 'USER_ENTERED'
                            ];
                            $response = $service->spreadsheets_values->append($spreadsheetId, $range, $requestBody, $params);
                        }
                    }
                }
            }
        } catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log( $e->getMessage() );
            return null;
            exit();
        }
    }

    //get all the spreadsheets
    public function get_spreadsheets()
    {
        $all_sheets = array();
        try {
            $client = self::getInstance();

            $service = new Google_Service_Drive($client);

            $optParams = array(
                'q' => "mimeType='application/vnd.google-apps.spreadsheet'"
            );
            $results = $service->files->listFiles($optParams);
            foreach ($results->files as $spreadsheet) {
                if (isset($spreadsheet['kind']) && $spreadsheet['kind'] == 'drive#file') {
                    $all_sheets[] = array(
                        'id' => $spreadsheet['id'],
                        'title' => $spreadsheet['name'],
                    );
                }
            }
        } catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log( $e->getMessage() );
            return null;
            exit();
        }
        return $all_sheets;
    }

    //get worksheets title
    public function get_worktabs($spreadsheet_id)
    {
        $work_tabs_list = array();
        try {
            $client = self::getInstance();
            $service = new Google_Service_Sheets($client);
            $work_sheets = $service->spreadsheets->get($spreadsheet_id);

            foreach ($work_sheets as $sheet) {
                $properties = $sheet->getProperties();
                $work_tabs_list[] = array(
                    'id' => $properties->getSheetId(),
                    'title' => $properties->getTitle(),
                );
            }
        } catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log( $e->getMessage() );
            return null;
            exit();
        }

        return $work_tabs_list;
    }

    /**
     * Function - Adding custom column header to the sheet
     * @param string $sheet_name
     * @param string $tab_name
     * @param array $gs_map_tags 
     * @since 1.0
     */
    public function add_header($sheetname, $tabname, $final_header_array, $old_header)
    {
        try{
        $client = self::getInstance();
        $service = new Google_Service_Sheets($client);
        $spreadsheetId = $this->getSpreadsheetId();
        $work_sheets = $service->spreadsheets->get($spreadsheetId);

        $field_tag_array[] = '';
        if (!empty($work_sheets)) {
            foreach ($work_sheets as $sheet) {

                $properties = $sheet->getProperties();
                $sheet_id = $properties->getSheetId();
                $worksheet_id = $this->getWorkTabId();
                if ($sheet_id == $worksheet_id) {
                    $worksheet_title = $properties->getTitle();
                    $field_tag = isset($_POST['gf-custom-ck']) ? $_POST['gf-custom-ck'] : array();
                    $field_tag_key = isset($_POST['gf-custom-header-key']) ? $_POST['gf-custom-header-key'] : "";
                    $field_tag_placeholder = isset($_POST['gf-custom-header-placeholder']) ? $_POST['gf-custom-header-placeholder'] : "";
                    $field_tag_column = isset($_POST['gf-custom-header']) ? $_POST['gf-custom-header'] : "";
                    if (!empty($field_tag)) {
                        foreach ($field_tag as $key => $value) {
                            $gf_key = $field_tag_key[$key];
                            $gf_val = (!empty($field_tag_column[$key])) ? $field_tag_column[$key] : $field_tag_placeholder[$key];
                            if ($gf_val !== "") {
                                $field_tag_array[$gf_key] = $gf_val;
                                $gravityform_tags[] = $gf_val;
                            }
                        }
                    }
                    $range = $worksheet_title . '!1:1';

                    $values = array(array_values(array_filter($field_tag_array)));

                    $count_old_header = (!empty($old_header)) ? (count($old_header)) : 0;
                    $count_new_header = (!empty($final_header_array)) ? (count($final_header_array)) : 0;
                    $data_values = array();

                    // If old header count is greater than new header count than empty the header
                    if ($count_old_header !== 0 && $count_old_header > $count_new_header) {
                        for ($i = 0; $i <= $count_old_header; $i++) {
                            $column_name = isset($final_header_array[$i]) ? $final_header_array[$i] : "";
                            if ($column_name !== "") {
                                $data_values[] = $column_name;
                            } else {
                                $data_values[] = "";
                            }
                        }
                    } else {

                        foreach ($final_header_array as $column_name) {
                            $data_values[] = $column_name;
                        }
                    }

                    $values = array($data_values);

                    $requestBody = new Google_Service_Sheets_ValueRange([
                        'values' => $values
                    ]);

                    $params = [
                        'valueInputOption' => 'USER_ENTERED'
                    ];
                    $response = $service->spreadsheets_values->update($spreadsheetId, $range, $requestBody, $params);
                }
            }
        }
     }catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log( $e->getMessage() );
            return null;
            exit();
        }

    }

    public function gsheet_print_google_account_email()
    {
        try {
          
            $google_sheet = new CF7GSC_googlesheet();
            $google_sheet->auth();
            $email = $google_sheet->gsheet_get_google_account_email();
            update_option('cf7gf_email_account', $email);
            return $email;
           
        } catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log( $e->getMessage() );
            return false;
        }
    }

    public function gsheet_get_google_account_email()
    {
        $google_account = $this->gsheet_get_google_account();

        if ($google_account) {
            return $google_account->email;
        } else {
            return "";
        }
    }

    public function gsheet_get_google_account()
    {

        try {
            $client = $this->getInstance();

            if (!$client) {
                return false;
            }

            $service = new Google_Service_Oauth2($client);
            $user = $service->userinfo->get();
        } catch (Exception $e) {
            Gs_Connector_Free_Utility::gs_debug_log(__METHOD__ . " Error in fetching user info: \n " . $e->getMessage());
            return false;
        }

        return $user;
    }

    public static function revokeToken_auto($access_code)
    {
        if (is_multisite()) {
            // Fetch API creds
            $api_creds = get_site_option('cf7gsc_free_api_creds');
        } else {
            // Fetch API creds
            $api_creds = get_option('cf7gsc_free_api_creds');
        }
        $newClientSecret = get_option('is_new_client_secret_cf7gscfree');
        $clientId = ($newClientSecret == 1) ? $api_creds['client_id_web'] : $api_creds['client_id_desk'];
        $clientSecret = ($newClientSecret == 1) ? $api_creds['client_secret_web'] : $api_creds['client_secret_desk'];

        $client = new Google_Client();
        $client->setClientId($clientId);
        $client->setClientSecret($clientSecret);
        $tokendecode = json_decode($access_code);
        $token = $tokendecode->access_token;
        $client->revokeToken($token);
    }

}
