<?php

require_once('database.php');

class Facebook
{
    private $url;
    private $fb_user;
    private $user_id = 0;
    private $app_id = '';
    private $app_secret = '';

    private $version = 'v2.4';
    private $api_url = 'https://graph.facebook.com/';
    private $fb_url  = 'https://facebook.com/';

    private $graph_api = '';
    private $scope = array('publish_actions', 'manage_pages', 'publish_pages', 'user_managed_groups');
    private $db;

    function __construct(){
        if(!empty($_SESSION['far_user_id']))
            $this->user_id = $_SESSION['far_user_id'];

        $this->url = baseUrl('');

        $this->graph_api = $this->api_url . $this->version . '/';
        $this->db = db::Instance();
        $this->check_fb_user();
    }

    private function check_fb_user()
    {
        if(!empty($_SESSION['far_user'])) {
            $user_settings = $_SESSION['far_user'];
            if (empty($user_settings['app_id']) || empty($user_settings['app_secret'])) {
                if (isset($_SESSION['fb_user'])) {
                    unset($_SESSION['fb_user']);
                }
            } else {
                $this->app_id = $user_settings['app_id'];
                $this->app_secret = $user_settings['app_secret'];
            }
        }
    }

    public function get_fb_user()
    {
        $user_settings = $_SESSION['far_user'];
        if(empty($user_settings['app_id']) || empty($user_settings['app_secret'])){
            return array(
                'loginUrl'      => false,
                'user'          => false
            );
        }

        if(empty($_SESSION['fb_user'])){
            $user = $_SESSION['far_user'];
            if((int)$user['fb_user_id'] > 1 && $user['fb_token'] != '' && $user['fb_logged_in'] == 1) {
                $fb_info = $this->get_user_info($user['fb_user_id'], $user['fb_token']);
                $check_fb = json_decode($fb_info);
                if (!empty($check_fb->name)) {
                    $fb_user['fb_user'] = $fb_info;
                    $fb_user['fb_user_id'] = $check_fb->id;
                    $fb_user['fb_user_name'] = $check_fb->name;
                    $fb_user['user'] = true;
                    $fb_user['link'] = $this->fb_url.$check_fb->id;
                    $fb_user['fb_token'] = $user['fb_token'];

                    $this->renew_tokens($user['id'], $user['fb_user_id'], $user['fb_token']);
                    $_SESSION['fb_user'] = $fb_user;

                    return $fb_user;
                }
            }
        }else{
            return $_SESSION['fb_user'];
        }

        return array(
        'loginUrl' => $this->get_login_url(),
        'fb_user_id' => $_SESSION['far_user']['fb_user_id'],
        'user' => false
        );

    }

    private function renew_tokens($user_id, $fb_user_id, $fb_token)
    {
        $query = "  UPDATE ".DB_TABLE_PREFIX."schedules
                    SET     fb_token = '".$fb_token."'
                    WHERE   user_id = '".$user_id."'
                        AND fb_user_id = '".$fb_user_id."'
                ";

        $this->db->query($query);
    }

    private function get_login_url()
    {
        $user_settings = $_SESSION['far_user'];
        $redirectUrl = $this->url . 'dashboard.php';

        $params = array(
            'client_id' => $user_settings['app_id'],
            'redirect_uri' => $redirectUrl,
            //'state' => $state,
            'scope' => implode(',', $this->scope),
            'auth_type' => 'rerequest'
        );

        return $this->fb_url . $this->version . '/dialog/oauth?' . http_build_query($params, null, '&');
    }

    function get_user_info($fb_user_id, $access_token)
    {
        $data = $this->check_file_get_contents($this->graph_api.$fb_user_id.'/?access_token='.$access_token);

        return $data;
    }

    function check_app($app_id, $app_secret)
    {
        $data = $this->check_file_get_contents($this->api_url.$app_id.'?fields=roles&access_token='.$app_id.'|'.$app_secret);
        $app = json_decode($data);

        if(isset($app->roles)){
            return true;
        }else{
            return false;
        }
    }

    function check_file_get_contents($url)
    {
        if(ini_get('allow_url_fopen'))
        {
            $result = file_get_contents($url);
        }
        else
        {
            $curl   =   curl_init();
            curl_setopt($curl,CURLOPT_URL,$url);
            curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,2);
            curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);

            $result = curl_exec($curl);

            curl_close($curl);
        }

        return $result;
    }

    public function save_fb_user()
    {
        if(isset($_GET['code']))
        {
            $redirectUrl = $this->url . 'dashboard.php';
            $user_settings = $_SESSION['far_user'];
            $params = array(
                'code' => $_GET['code'],
                'client_id' => $user_settings['app_id'],
                'client_secret' => $user_settings['app_secret'],
                'redirect_uri' => $redirectUrl,
            );

            $token_data = $this->check_file_get_contents($this->graph_api.'oauth/access_token?'.http_build_query($params, null, '&'));
            $token_data = json_decode($token_data);

            if(!empty($token_data->access_token)){
                $user_data = $this->check_file_get_contents($this->graph_api.'me?fields=email,name&access_token='.$token_data->access_token);
                $user_data = json_decode($user_data);
                if(!empty($user_data)){
                    if($user_settings['fb_user_id'] == $user_data->id || $user_settings['fb_user_id'] == '' || $user_settings['fb_user_id'] == '0'){
                        $this->set_long_live_token($token_data->access_token);
                        $upd_data['fb_user_id']     = $user_data->id;
                        $upd_data['fb_token']       = $token_data->access_token;
                        $upd_data['fb_user_name']   = $user_data->name;
                        $upd_data['fb_logged_in']   = 1;
                        $this->db->update(DB_TABLE_PREFIX."users",$upd_data,$user_settings['id']);

                        $this->renew_tokens($user_settings['id'], $user_data->id, $token_data->access_token);

                        if(isset($_SESSION['fb_user'])){
                            unset($_SESSION['fb_user']);
                        }

                        $this->get_fb_user();
                    }
                }
            }

            header('Location: '.baseUrl('dashboard.php'));
            die();
        }
    }

    public function fb_logout()
    {
        if(isset($_SESSION['fb_user'])){
            unset($_SESSION['fb_user']);
        }

        $upd_data['fb_logged_in']   = 0;
        $this->db->update(DB_TABLE_PREFIX.'users',$upd_data,$this->user_id);

    }

    private function set_long_live_token($access_token)
    {
        $access_token_info = $this->check_file_get_contents($this->graph_api.'/oauth/access_token_info?client_id='.$this->app_id.'&access_token='.$access_token);
        $access_token_info = json_decode($access_token_info);

        $token_result = false;

        if(isset($access_token_info->access_token) && isset($access_token_info->expires_in))
        {
            $token_result = true;
        }
        else if(isset($access_token_info->access_token) && !isset($access_token_info->expires_in))
        {
            $token_result = false;
        }

        if($token_result)
        {
            $result = $this->check_file_get_contents($this->graph_api.'/oauth/access_token?grant_type=fb_exchange_token&client_id='.$this->app_id.'&client_secret='.$this->app_secret.'&fb_exchange_token='.$access_token);
            return true;
        }

        return false;
    }

    function get_fan_pages_list($fb_user_id = 0, $access_token = "", $limit = 5000)
    {
        $result = array('data' => "", 'erorr' => "", 'status' => 1);

        if($fb_user_id == 0){
            $result['status'] = 2;
            $result['error'] = "Facebook error: Fan Pages could not be retrieved!";
            return $result;
        }

        $data = $this->check_file_get_contents($this->graph_api.$fb_user_id.'/accounts?fields=likes,name&access_token='.$access_token);

        $pages = json_decode($data);

        $i = 0;
        $over_limit = false;
        if(!empty($pages->data))
            foreach($pages->data as $page)
            {
                if($i == $limit) {$over_limit = true; break;}
                $result['data'][] = array('id' => $page->id, 'name' => $page->name, 'likes' => $page->likes);
                $i++;
            }

        if(!empty($pages->error)){
            $result['status'] = 2;
            foreach($pages->error as $error)
                $result['error'] = $error->message;
        }

        if($over_limit){
            return $result;
        }

        $is_next = false;
        if(!empty($pages->paging)){
            $paging = $pages->paging;
            if(!empty($paging->next)){
                $url = $paging->next;
                $is_next = true;
            }
        }

        while($is_next)
        {
            $data = $this->check_file_get_contents($url);

            $pages = json_decode($data);

            if(!empty($pages->data))
                foreach($pages->data as $page)
                {
                    if($i == $limit) {$over_limit = true; break;}
                    $result['data'][] = array('id' => $page->id, 'name' => $page->name, 'likes' => $page->likes);
                    $i++;
                }

            if(!empty($pages->error)){
                $result['status'] = 2;
                foreach($pages->error as $error)
                    $result['error'] = $error->message;
            }

            $is_next = false;
            if(!empty($pages->paging) && empty($pages->error) && !$over_limit){
                $paging = $pages->paging;
                if(!empty($paging->next)){
                    $url = $paging->next;
                    $is_next = true;
                }
            }
        }

        return $result;

    }

    public function check_group_access($group_id, $access_token)
    {
        $data = $this->check_file_get_contents($this->graph_api.$group_id.'/?fields=privacy,id,name&access_token='.$access_token);
        $group = json_decode($data);

        if(isset($group->privacy) && strtolower($group->privacy) != 'closed')
            $closed = 0;
        else
            $closed = 1;

        if(!empty($group->id)){
            return array('id' => $group->id, 'name' => $group->name, 'closed' => $closed);
        }

        return false;
    }

    public function get_groups_list($fb_user_id = 0, $access_token = "", $limit = 5000)
    {
        $result = array('data' => "", 'erorr' => "", 'status' => 1);

        if($fb_user_id == 0){
            $result['status'] = 2;
            $result['error'] = "Facebook error: Fan Pages could not be retrieved!";
            return $result;
        }

        $data = $this->check_file_get_contents($this->graph_api.$fb_user_id.'/groups?fields=privacy,name,administrator&access_token='.$access_token);

        $groups = json_decode($data);

        $i = 0;
        $over_limit = false;
        if(!empty($groups->data))
            foreach($groups->data as $group)
            {
                if(empty($group->administrator) || !($group->administrator)) continue;

                if($i == $limit) {$over_limit = true; break;}
                if(isset($group->privacy) && strtolower($group->privacy) != 'closed')
                    $closed = 0;
                else
                    $closed = 1;

                $result['data'][] = array('id' => $group->id, 'name' => $group->name, 'closed' => $closed);
                $i++;
            }

        if(!empty($groups->error)){
            $result['status'] = 2;
            foreach($groups->error as $error)
                $result['error'] = $error->message;
        }

        if($over_limit){
            return $result;
        }

        $is_next = false;
        if(!empty($groups->paging)){
            $paging = $groups->paging;
            if(!empty($paging->next)){
                $url = $paging->next;
                $is_next = true;
            }
        }

        while($is_next)
        {
            $data = $this->check_file_get_contents($url);

            $groups = json_decode($data);

            if(!empty($groups->data))
                foreach($groups->data as $group)
                {
                    if(empty($group->administrator) || !($group->administrator)) continue;

                    if(isset($group->privacy) && strtolower($group->privacy) != 'closed')
                        $closed = 0;
                    else
                        $closed = 1;

                    if($i == $limit) {$over_limit = true; break;}
                    $result['data'][] = array('id' => $group->id, 'name' => $group->name, 'closed' => $closed);
                    $i++;
                }

            if(!empty($groups->error)){
                $result['status'] = 2;
                foreach($groups->error as $error)
                    $result['error'] = $error->message;
            }

            if($over_limit){
                return $result;
            }

            $is_next = false;
            if(!empty($groups->paging) && empty($groups->error) && !$over_limit){
                $paging = $groups->paging;
                if(!empty($paging->next)){
                    $url = $paging->next;
                    $is_next = true;
                }
            }
        }

        return $result;
    }

    public function getObjectPosts($object_id, $access_token, $limit = 100, $only_owner = true, $with_comments = false, $with_likes = false){

        $comm = '';
        $like = '';
        if($with_comments){
            $comm = ',comments.limit(0).summary(true)';
        }

        if($with_likes){
            $like = ',likes.limit(0).summary(true)';
        }

        $data = $this->check_file_get_contents($this->graph_api.$object_id.'/feed?fields=message,from,created_time,picture'.$comm.$like.'&limit='.$limit.'&access_token='.$access_token.'&since=0');

        $result = array();
        $posts = json_decode($data);

        if(!empty($posts->data))
            foreach($posts->data as $post) {
                $owner = $post->from;
                if($only_owner){
                    if($owner->id == $object_id)
                        $result[] = $post;
                }else{
                    if($owner->id != $object_id)
                        $result[] = $post;
                }

                if(count($result) >= $limit) break;
            }

        if(!empty($posts->paging) && count($result) < $limit){
            $check = true;

            while($check){
                if(!empty($posts->paging->next)){
                    $data = $this->check_file_get_contents($posts->paging->next);
                    $posts = json_decode($data);

                    if(!empty($posts->data))
                        foreach($posts->data as $post){
                            $owner = $post->from;
                            if($only_owner){
                                if($owner->id == $object_id)
                                    $result[] = $post;
                            }else{
                                if($owner->id != $object_id)
                                    $result[] = $post;
                            }

                            if(count($result) >= $limit) break;
                        }

                    if(count($result) >= $limit)
                        $check = false;

                }else{
                    $check = false;
                }
            }
        }

        return $result;
    }

    public function get_post_info($post_id, $access_token)
    {
        //$data = $this->check_file_get_contents($this->graph_api.$post_id.'/?fields=created_time,link,message,picture,shares&access_token='.$access_token);
    }

    public function get_page_token($fb_user_id, $access_token, $page_id)
    {
        $page_token = $access_token;
        $data = $this->check_file_get_contents($this->graph_api.$fb_user_id.'/accounts?access_token='.$access_token);

        $data = json_decode($data);
        if(!empty($data->data))
            foreach($data->data as $page)
            {
                if($page->id == $page_id)
                    $page_token = $page->access_token;
            }

        return $page_token;
    }

    public function set_comment($object_id, $access_token, $message, $id)
    {
        $message = urlencode($message);
        $params[] = "message=".$message;
        $params = implode('&',$params);
        //$params = http_build_query(array('message'=>$message),null,'&');

        $curl = curl_init($this->graph_api.$object_id.'/comments?access_token='.$access_token);
        curl_setopt($curl,CURLOPT_POST,true);
        curl_setopt($curl,CURLOPT_POSTFIELDS,$params);
        curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
        curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,0);
        curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);

        $response = curl_exec($curl);

        curl_close($curl);

        $result = false;
        $comment = json_decode($response);

        if(!empty($comment->id))
            $result = $comment->id;
        else{
            $upd_data = array();
            $upd_data['error'] = $response;
            $this->db->update(DB_TABLE_PREFIX.'schedules_queue',$upd_data,$id);
        }

        return $result;
    }

    public function get_object_info($object_id, $access_token, $fields = '')
    {
        $fields = empty($fields) ? : 'fields='.$fields.'&';
        $data = $this->check_file_get_contents($this->graph_api.$object_id.'?'.$fields.'access_token='.$access_token);

        $response = json_decode($data);

        return $response;
    }

    public function get_object_comments_info($object_id, $access_token)
    {
        $data = $this->check_file_get_contents($this->graph_api.$object_id.'/comments/?summary=true&limit=0&access_token='.$access_token);

        $response = json_decode($data);

        return $response;
    }

    public function get_object_likes_info($object_id, $access_token)
    {
        $data = $this->check_file_get_contents($this->graph_api.$object_id.'/likes/?summary=true&limit=0&access_token='.$access_token);

        $response = json_decode($data);

        return $response;
    }

    public function check_token_time($access_token, $app_id, $time)
    {
        $access_token_info = $this->check_file_get_contents($this->graph_api.'oauth/access_token_info?client_id='.$app_id.'&access_token='.$access_token);
        $access_token_info = json_decode($access_token_info);

        if(isset($access_token_info->access_token) && isset($access_token_info->expires_in))
        {
            if($access_token_info->expires_in <= 0)
                return false;
            else
                return true;
        }
        else if(isset($access_token_info->access_token) && !isset($access_token_info->expires_in))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public function get_token_time($access_token, $time)
    {
        $access_token_info = $this->check_file_get_contents($this->graph_api.'oauth/access_token_info?client_id='.$this->app_id.'&access_token='.$access_token);
        $access_token_info = json_decode($access_token_info);

        if(isset($access_token_info->access_token) && isset($access_token_info->expires_in))
        {
            return $this->timespan($time - $access_token_info->expires_in, $time);
        }
        else if(isset($access_token_info->access_token) && !isset($access_token_info->expires_in))
        {
            return 'This token does not expire.';
        }
        else
        {
            return 'Could not get token expire time.';
        }
    }

    private function timespan($seconds = 1, $time = '')
    {
        if ( ! is_numeric($seconds))
        {
            $seconds = 1;
        }

        if ( ! is_numeric($time))
        {
            $time = time();
        }

        if ($time <= $seconds)
        {
            $seconds = 1;
        }
        else
        {
            $seconds = $time - $seconds;
        }

        $str = '';
        $years = floor($seconds / 31536000);

        if ($years > 0)
        {
            $str .= $years.' '.($years	> 1) ? ' years' : ' year'.', ';
        }

        $seconds -= $years * 31536000;
        $months = floor($seconds / 2628000);

        if ($years > 0 OR $months > 0)
        {
            if ($months > 0)
            {
                $str .= $months.' '.($months	> 1) ? ' months' : ' month'.', ';
            }

            $seconds -= $months * 2628000;
        }

        $weeks = floor($seconds / 604800);

        if ($years > 0 OR $months > 0 OR $weeks > 0)
        {
            if ($weeks > 0)
            {
                $str .= $weeks.' '.($weeks	> 1) ? ' weeks' : ' week'.', ';
            }

            $seconds -= $weeks * 604800;
        }

        $days = floor($seconds / 86400);

        if ($months > 0 OR $weeks > 0 OR $days > 0)
        {
            if ($days > 0)
            {
                $str .= $days.' '.($days	> 1) ? ' days' : ' day'.', ';
            }

            $seconds -= $days * 86400;
        }

        $hours = floor($seconds / 3600);

        if ($days > 0 OR $hours > 0)
        {
            if ($hours > 0)
            {
                $str .= $hours.' '.($hours	> 1) ? ' hours' : ' hour'.', ';
            }

            $seconds -= $hours * 3600;
        }

        $minutes = floor($seconds / 60);

        if ($days > 0 OR $hours > 0 OR $minutes > 0)
        {
            if ($minutes > 0)
            {
                $str .= $minutes.' '. ($minutes	> 1) ? ' minutes' : ' minute'.', ';
            }

            $seconds -= $minutes * 60;
        }

        if ($str == '')
        {
            $str .= $seconds.' '.($seconds	> 1) ? ' seconds' : ' second'.', ';
        }

        return substr(trim($str), 0, -1);
    }

    public function getComments($object_id, $access_token, $page_id, $limit = 100){
        $data = $this->check_file_get_contents($this->graph_api.$object_id.'/comments?fields=from,message,id,can_comment&access_token='.$access_token);

        $result = array();
        $comments = json_decode($data);

        if(!empty($comments->data))
            foreach($comments->data as $comment) {
                $owner = $comment->from;
                if ($owner->id != $page_id) {
                    $result[] = $comment;
                }
            }

        if(!empty($comments->paging) && count($result) < $limit){
            $check = true;

            while($check){
                if(!empty($comments->paging->next)){
                    $data = $this->check_file_get_contents($comments->paging->next);
                    $comments = json_decode($data);

                    if(!empty($comments->data))
                        foreach($comments->data as $comment){
                            $owner = $comment->from;
                            if ($owner->id != $page_id) {
                                $result[] = $comment;
                            }
                        }

                    if(count($result) >= $limit)
                        $check = false;

                }else{
                    $check = false;
                }
            }
        }

        return $result;
    }

    public function delete_comment($comment_id, $access_token)
    {
        $data = $this->check_file_get_contents($this->graph_api.$comment_id.'?access_token='.$access_token.'&method=delete');

        $response = json_decode($data);

        if(!empty($response->success)){
            return $response->success;
        }else{
            return false;
        }
    }

    public function get_group_info($group_id, $access_token)
    {
        $data = $this->check_file_get_contents($this->graph_api.$group_id.'?access_token='.$access_token);

        $response = json_decode($data);

        return $response;
    }


    public function import_groups($user_id, $fb_token, $file)
    {
        if(!empty($file)) {
            $groups = array();
            $string = @file_get_contents($file);

            preg_match_all('/"id":"(\d+)","name":"([^"]+)","count":([^"]+)/', $string, $matches);

            if (isset($matches[1]) && isset($matches[2]) && isset($matches[3])) {
                $i = 0;
                foreach ($matches[1] as $key => $row) {
                    if ((isset($matches[3][$key]) && $matches[3][$key] == 'null,')) break;

                    $decode = json_decode('["' . $matches[2][$key] . '"]');
                    $groups[$i]['id'] = $matches[1][$key];
                    $groups[$i]['name'] = isset($decode[0]) ? $decode[0] : $matches[2][$key];

                    $i++;
                }

                if (!empty($groups)) {
                    $this->save_user_groups($user_id, $groups);
                    @unlink($file);
                    return true;
                }
            }

            if (empty($groups)) {
                preg_match_all('/\/groups\/(\w+)\//', $string, $matches);

                if (!empty($matches[1])) {
                    $i = 0;
                    foreach ($matches[1] as $group) {
                        $data = $this->get_group_info($group, $fb_token);

                        if (isset($data->id) && $data->id == $group && isset($data->name)) {
                            $groups[$i]['id'] = $data->id;
                            $groups[$i]['name'] = $data->name;
                        }

                        $i++;
                    }

                }

                if (!empty($groups)) {
                    $this->save_user_groups($user_id, $groups);
                    @unlink($file);
                    return true;
                }
            }

            if (empty($groups)) {
                $this->save_user_groups($user_id, array());
                return true;
            }

        }

        return false;
    }

    private function save_user_groups($user_id, $groups)
    {
        if(count($groups) == 0){
            $this->db->delete(DB_TABLE_PREFIX."user_groups",$user_id,'user_id');
            return true;
        }

        $exists = $this->db->selectOne("SELECT * FROM ".DB_TABLE_PREFIX."user_groups WHERE user_id = '".$user_id."'");
        $ins_data['groups'] = json_encode($groups);
        if(empty($exists)){
            $ins_data['user_id'] = $user_id;
            $this->db->insert(DB_TABLE_PREFIX."user_groups",$ins_data);
        }else{
            $this->db->update(DB_TABLE_PREFIX."user_groups",$ins_data,$exists['id']);
        }

        return true;
    }

    public function load_user_groups($user_id)
    {
        $groups = $this->db->selectOne("SELECT * FROM ".DB_TABLE_PREFIX."user_groups WHERE user_id = '".$user_id."'");

        if(!empty($groups))
            return json_decode(html_entity_decode($groups['groups']));
        else
            return array();
    }
}