<?php
namespace Valhalla\BaseBundle\Classes\Widgets;

use Valhalla\CoreUtilities\Http\Request\cURL;

class Twitter {

    const OAUTH_ACCESS_TOKEN = "put your access token here";
    const OAUTH_ACCESS_TOKEN_SECRET = "put your access secret here";
    const CONSUMER_KEY = "put your consumer key here";
    const CONSUMER_SECRET = "put your consumer secret here";

    const DEFAULT_COUNT = 5;

    /**
     * Gets the $count most recent tweets
     *
     * @param int $count
     * @param boolean $raw If true, return the raw API result
     * @return array
     */
    public function getTweets($count = self::DEFAULT_COUNT, $raw = false) {
        $getTweetsUrl = "https://api.twitter.com/1.1/statuses/user_timeline.json";

        $params = array(
            'count' => $count,
        );

        $oauth = $this->getSignedData($getTweetsUrl, 'GET', $params);
        $data = $this->requestData($getTweetsUrl, $params, $oauth);

        if($raw){
            return $data;
        } else {
            return $this->formatTweets($data);
        }
    }

    /**
     * Makes the tweet data nicer to work with
     *
     * @param array $data
     * @return array
     */
    public function formatTweets($data){
        $tweets = array();

        foreach($data as $tweetData){
            $retweet = false;
            if(!empty($tweetData['retweeted_status'])){
                $tweetData = $tweetData['retweeted_status'];
                $retweet = true;
            }
            $user = array(
                'name' => $tweetData['user']['name'],
                'username' => $tweetData['user']['screen_name'],
                'avatar' => $tweetData['user']['profile_image_url'],
                'url' => 'https://twitter.com/' . $tweetData['user']['screen_name'],
            );

            $text = $tweetData['text'];
            foreach($tweetData['entities']['urls'] as $url){
                $text = str_replace($url['url'], "<a href='{$url['expanded_url']}' rel='nofollow'>{$url['display_url']}</a>", $text);
            }
            $text = preg_replace('/(?<=^|\s)@([a-z0-9_]+)/i', '<a href="https://www.twitter.com/$1" rel="nofollow">@$1</a>', $text);
            foreach($tweetData['entities']['hashtags'] as $hashtag){
                $text = str_replace("#{$hashtag['text']}", "<a href='https://twitter.com/hashtag/{$hashtag['text']}?src=hash' rel='nofollow'>#{$hashtag['text']}</a>", $text);
            }

            $tweets[] = array(
                'text' => $text,
                'date' => date('M d', strtotime($tweetData['created_at'])),
                'user' => $user,
                'isRetweet' => $retweet,
            );
        }

        return $tweets;
    }

    /**
     * Creates the OAuth data with the signature for the request.
     *
     * @param string $url
     * @param string $method
     * @param array $params
     * @return array
     */
    public function getSignedData($url, $method = 'GET', $params = array()){
        $oauth = array('oauth_consumer_key' => self::CONSUMER_KEY,
            'oauth_nonce' => time(),
            'oauth_signature_method' => 'HMAC-SHA1',
            'oauth_token' => self::OAUTH_ACCESS_TOKEN,
            'oauth_timestamp' => time(),
            'oauth_version' => '1.0'
        );
        $baseInfo = $this->buildBaseString($url, $method, array_merge($oauth, $params));
        $compositeKey = rawurlencode(self::CONSUMER_SECRET) . '&' . rawurlencode(self::OAUTH_ACCESS_TOKEN_SECRET);
        $oauth['oauth_signature'] = base64_encode(hash_hmac('sha1', $baseInfo, $compositeKey, true));

        return $oauth;
    }

    /**
     * Requests the data from the API given request params and the OAuth data
     *
     * @param string $url
     * @param array $params
     * @param array $oauth
     * @return array
     */
    protected function requestData($url, $params, $oauth) {
        $header = array($this->buildAuthorizationHeader($oauth), 'Expect:');
        $options = array(
            'CURLOPT_HTTPHEADER' => $header,
            'CURLOPT_HEADER' => false,
        );

        try{
            $curl = new cURL();
            $curl->setOptions($options);
            $json = $curl->get($url . '?' . http_build_query($params));
        } catch(\Exception $e){
            $json = array(); //nothing should die if we can't get tweets
        }

        return json_decode($json, true);
    }

    /**
     * Builds the string for the HMAC
     *
     * @param string $baseURI
     * @param string $method
     * @param array $params
     * @return string
     */
    protected function buildBaseString($baseURI, $method, $params) {
        $paramString = array();
        ksort($params);
        foreach ($params as $key => $value) {
            $paramString[] = "$key=" . rawurlencode($value);
        }

        return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $paramString));
    }

    /**
     * Builds the HTTP header for OAuth
     *
     * @param array $oauth
     * @return string
     */
    protected function buildAuthorizationHeader($oauth) {
        $headerString = 'Authorization: OAuth ';
        $values = array();
        foreach ($oauth as $key => $value){
            $values[] = "$key=\"" . rawurlencode($value) . "\"";
        }
        $headerString .= implode(', ', $values);

        return $headerString;
    }
}