<?php

require_once __DIR__ . "/../../../../extensions/HybridAuth/hybridauth-2.6.0/hybridauth/Hybrid/Providers/Google.php";

class plGoogle extends Hybrid_Providers_Google
{

    public $model;

    public function getTotalContactCount()
    {
        $this->refreshAccessToken();
        $totalItemCount = 0;
        if (!isset($this->config['contacts_param'])) {
            $this->config['contacts_param'] = array("start-index" => 1, "max-results" => 0);
        }
        $response = $this->sendGetContactsRequest();
        if (isset($response->feed)) {
            $totalItemsKey = 'openSearch$totalResults';
            if (property_exists($response->feed, $totalItemsKey)) {
                $value = '$t';
                $totalItemCount = $response->feed->$totalItemsKey->$value;
            }
        }
        return $totalItemCount;
    }

    private function sendGetContactsRequest()
    {
        return $this->api->api("https://www.google.com/m8/feeds/contacts/default/full?"
                        . http_build_query(array_merge(array('alt' => 'json', 'v' => '3.0'), $this->config['contacts_param'])));
    }

    public function getContacts($attributes)
    {
        $this->model = $attributes['model'];
        $this->refreshAccessToken();
        if (!isset($this->config['contacts_param'])) {
            $this->config['contacts_param'] = array("start-index" => $attributes['offset'], "max-results" => $attributes['limit']);
        }
        if (strpos($this->scope, '/m8/feeds/') !== false) {
            $response = $this->sendGetContactsRequest();
            if (property_exists($response, 'feed') && isset($response->feed->entry)) {
                $this->importAddresses($response->feed->entry);
            }
        }
    }

    private function refreshAccessToken()
    {
        if ($this->api->access_token) {
            if ($this->api->refresh_token && $this->api->access_token_expires_at) {
                if ($this->api->access_token_expires_at <= time()) {
                    $this->updateAccessData();
                }
            }
            $this->token("access_token", $this->api->access_token);
            $this->token("refresh_token", $this->api->refresh_token);
            $this->token("expires_in", $this->api->access_token_expires_in);
            $this->token("expires_at", $this->api->access_token_expires_at);
        }
    }

    private function updateAccessData()
    {
        $response = $this->api->refreshToken(array("refresh_token" => $this->api->refresh_token));
        if (!isset($response->access_token) || !$response->access_token) {
            $this->setUserUnconnected();
            throw new Exception("The Authorization Service has return an invalid response while requesting a new access token. " . (string) $response->error);
        }
        $this->api->access_token = $response->access_token;
        $this->api->curl_header = array('Authorization: OAuth ' . $response->access_token);
        if (isset($response->refresh_token)) {
            $this->api->refresh_token = $response->refresh_token;
        }
        if (isset($response->expires_in)) {
            $this->api->access_token_expires_in = $response->expires_in;
            $this->api->access_token_expires_at = time() + $response->expires_in;
        }
    }

    private function importAddresses($contacts)
    {
        foreach ($contacts as $entry) {
            $address = get_object_vars($entry);
            $this->importAddress($address);
        }
    }

    private function importAddress($contactData)
    {
        $address = $this->getAddressesModel($contactData);
        $this->setModelData($address);
        
        if (isset($contactData['content'])) {
            $value = '$t';
            if (property_exists($contactData['content'], $value)) {
                $address->contact_note = $contactData['content']->$value;
            }
        }
        if (isset($contactData['gd$name'])) {
            $this->setNames($address, $contactData['gd$name']);
        }
        if (isset($contactData['gContact$birthday'])) {
            if (property_exists($contactData['gContact$birthday'], 'when')) {
                $address->contact_bday = PhonalisaDate::newServerDate($contactData['gContact$birthday']->when, "Y-m-d");
            }
        }
        if (isset($contactData['gd$organization'])) {
            if (isset($contactData['gd$organization'][0])) {
                $this->setOrganization($address, $contactData['gd$organization'][0]);
            }
        }
        if (isset($contactData['gd$structuredPostalAddress'])) {
            $this->setAddresses($address, $contactData['gd$structuredPostalAddress']);
        }
        if (isset($contactData['gContact$website'])) {
            $this->setWebsite($address, $contactData['gContact$website']);
        }
        if (isset($contactData['gd$email'])) {
            $this->setEMail($address, $contactData['gd$email']);
        }
        if (isset($contactData['gd$phoneNumber'])) {
            $this->setPhoneNumber($address, $contactData['gd$phoneNumber']);
        }
        if (isset($contactData['link'])) {
            
            //FIXME
            // -> sorgt für 500er error siehe Ticket kommentar: 0002295: google Import
            
            // $this->getPhoto($address, $contactData['link']);
        }
        
        if ($this->hasImportRelevantData($address)) {
            if (!$address->save()) {
                Log::e('An error has occurred saving addresses model', 'ThirdPartyCredentials [plGoogle]');
                Log::e('User-ID: ' . $this->address->contact_owner, 'ThirdPartyCredentials [plGoogle]');
                Log::e('Error Text: ' . json_encode($this->address->errors), 'ThirdPartyCredentials [plGoogle]');
            }
        }
        
    }
    
    protected function hasImportRelevantData($address)
    {
        $importRelevantAttributes = array_keys(Addresses::csvRelevantAttributes());
        foreach ($importRelevantAttributes as $attribute) {
            if (!empty($address->$attribute)) {
                return true;
            } 
        }
        return false;
    }

    private function getAddressesModel($contactData)
    {
        $value = '$t';
        $id = property_exists($contactData['id'], $value) ? basename($contactData['id']->$value) : '';
        $address = Addresses::model()->findByAttributes(
                array('googleId' => $id,
                    'contact_tid' => $this->model->addressBookId
                )
        );
        if (!isset($address)) {
            $address = new Addresses();
            $address->googleId = $id;
        }

        return $address;
    }

    private function setModelData($address)
    {
        $address->contact_tid = $this->model->addressBookId;
        $address->contact_owner = $this->model->owner;
        $address->source = AddressSourceType::getSourceTypeFromProvider($this->model->provider);
    }

    private function getPhoto($address, $photoIds)
    {
        foreach ($photoIds as $id) {
            if (property_exists($id, 'type') && $id->type == 'image/*') {
                $address->contact_jpegphoto = property_exists($id, 'href') ? $id->href : "";
                if (isset($address->contact_jpegphoto)) {
                    $this->downloadPhoto($address);
                }
            }
        }
    }

    private function downloadPhoto($address)
    {
        $result = $this->request($address->contact_jpegphoto);
        if ($result && ($result != "Photo not found")) {
            $tempPath = Yii::app()->runtimePath . "/$address->googleId";
            file_put_contents($tempPath, $result);
            $address->contact_jpegphoto = '1';
            $address->save();
            $address->saveImage($tempPath);
        }
    }

    private function request($url)
    {
        $parameters[$this->api->sign_token_name] = $this->api->access_token;
        $url = $url . ( strpos($url, '?') ? '&' : '?' ) . http_build_query($parameters, '', '&');
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $response = curl_exec($ch);

        curl_close($ch);

        return $response;
    }

    private function setNames($address, $googleCredentials)
    {

        $attributes = array(
            'n_prefix' => 'gd$namePrefix',
            'n_fn' => 'gd$fullName',
            'n_middle' => 'gd$additionalName',
            'n_given' => 'gd$givenName',
            'n_family' => 'gd$familyName',
            'n_suffix' => 'gd$nameSuffix'
        );
        $this->setAttributes($attributes, $address, $googleCredentials);
    }

    private function setOrganization($address, $googleCredentials)
    {
        $attributes = array(
            'org_name' => 'gd$orgName',
            'contact_role' => 'gd$orgTitle'
        );
        $this->setAttributes($attributes, $address, $googleCredentials);
    }

    private function setAddresses($address, $googleCredentials)
    {
        foreach ($googleCredentials as $contactAddress) {
            if (property_exists($contactAddress, 'rel')) {
                $addresstype = substr($contactAddress->rel, stripos($contactAddress->rel, '#') + 1);
                if ($addresstype == 'work') {
                    $this->setWorkAddresses($address, $contactAddress);
                }
                if ($addresstype == 'home') {
                    $this->setHomeAddresses($address, $contactAddress);
                }
            }
        }
    }

    private function setWebsite($address, $googleCredentials)
    {
        foreach ($googleCredentials as $website) {
            if (property_exists($website, 'rel') && $website->rel == 'work') {
                $address->contact_url = property_exists($website, 'href') ? $website->href : "";
            }
            if (property_exists($website, 'rel') && $website->rel == 'home') {
                $address->contact_url_home = property_exists($website, 'href') ? $website->href : "";
            }
        }
    }

    private function setEMail($address, $googleCredentials)
    {
        foreach ($googleCredentials as $contactEMail) {

            if (property_exists($contactEMail, 'rel')) {
                $addresstype = substr($contactEMail->rel, stripos($contactEMail->rel, '#') + 1);
                if ($addresstype == 'work') {
                    $address->contact_email = $contactEMail->address;
                }
                if ($addresstype == 'home') {
                    $address->contact_email_home = $contactEMail->address;
                }
            }
        }
    }

    private function setPhoneNumber($address, $googleCredentials)
    {
        $value = '$t';
        $attributes = array(
            'work' => 'tel_work',
            'home' => 'tel_home',
            'mobile' => 'tel_cell',
            'work_fax' => 'tel_fax',
            'home_fax' => 'tel_fax_home',
            'pager' => 'tel_pager'
        );
        foreach ($googleCredentials as $phoneNumber) {
            if (property_exists($phoneNumber, 'rel')) {
                $addresstype = substr($phoneNumber->rel, stripos($phoneNumber->rel, '#') + 1);
                if (isset($attributes[$addresstype])) {
                    $address->$attributes[$addresstype] = $phoneNumber->$value;
                }
            }
        }
    }

    private function setWorkAddresses($address, $workAddress)
    {
        $attributes = array(
            'adr_one_street' => 'gd$street',
            'adr_one_street2' => '',
            'adr_one_locality' => 'gd$city',
            'adr_one_region' => 'gd$region',
            'adr_one_postalcode' => 'gd$postcode',
            'adr_one_countryname' => 'gd$country'
        );
        $this->setAttributes($attributes, $address, $workAddress);
    }

    private function setHomeAddresses($address, $homeAddress)
    {
        $attributes = array(
            'adr_two_street' => 'gd$street',
            'adr_two_street2' => '',
            'adr_two_locality' => 'gd$city',
            'adr_two_region' => 'gd$region',
            'adr_two_postalcode' => 'gd$postcode',
            'adr_two_countryname' => 'gd$country'
        );
        $this->setAttributes($attributes, $address, $homeAddress);
    }

    private function setAttributes($attributesList, $address, $googleCredentials)
    {
        foreach ($attributesList as $attribute => $googleAttribute) {
            if (property_exists($googleCredentials, $googleAttribute)) {
                $value = '$t';
                if (property_exists($googleCredentials->$googleAttribute, $value)) {
                    $address->$attribute = $googleCredentials->$googleAttribute->$value;
                }
            }
        }
    }
}
