<?php

require_once('database.php');
require_once('fb.php');

class Cron {
    private $db;
    private $facebook;


    private $timezone;

    function __construct(){
        $this->db = db::Instance();
        $this->facebook = new Facebook();

        $this->set_cron_run();
    }

    public function timestamp($user_id = 0)
    {
        $gmt_zone = "Europe/London";
        if(!$user_id)
        {
            $user_tmp = $this->db->selectOne("SELECT timezone FROM ".DB_TABLE_PREFIX."users WHERE id='".$user_id."'");
            $gmt_zone = empty($user_tmp['timezone']) ? 'Europe/London' : $user_tmp['timezone'];
        }

        $timezone = new DateTimeZone($gmt_zone);
        $offset   = $timezone->getOffset(new DateTime("now"));

        return strtotime(gmdate("M d Y H:i:s", time())) + $offset;
    }

    public function user_timestamp()
    {
        $timezone = new DateTimeZone($this->timezone);
        $offset   = $timezone->getOffset(new DateTime("now"));

        return strtotime(gmdate("M d Y H:i:s", time())) + $offset;
    }

    private function set_cron_run(){
        $timestamp = $this->timestamp();
        $last_run = $this->db->selectOne("SELECT * FROM ".DB_TABLE_PREFIX."global_config WHERE `param` = 'last_cron_run'");

        $ins_data['value'] = $timestamp;
        if(empty($last_run)){
            $ins_data['param'] = 'last_cron_run';
            $this->db->insert(DB_TABLE_PREFIX.'global_config',$ins_data);
        }else{
            $this->db->update(DB_TABLE_PREFIX.'global_config',$ins_data,$last_run['id']);
        }

        return true;
    }

    public function cron()
    {
        //echo "<br>start time: ".time()."<br>";
        $users = $this->db->query("SELECT u.* FROM ".DB_TABLE_PREFIX."users u WHERE u.app_id <> '' AND (EXISTS(SELECT 1 FROM ".DB_TABLE_PREFIX."schedules c WHERE c.user_id = u.id AND c.status = 1) OR EXISTS(SELECT 1 FROM ".DB_TABLE_PREFIX."schedules_queue q WHERE q.user_id = u.id AND q.status <> 3))");
        if(empty($users))
            return true;

        foreach($users as $user)
        {
            $user_id = $user['id'];
            $this->timezone = $user['timezone'];
            $timestamp = $this->user_timestamp();
            echo "user id: ".$user['id']." | timestamp: ".$timestamp."<br>";

            if(!$this->facebook->check_token_time($user['fb_token'],$user['app_id'],$timestamp)){
                // send email
                continue;
            }

            $schedules = $this->db->select("SELECT c.id FROM ".DB_TABLE_PREFIX."schedules c WHERE c.`status` = 1 AND c.user_id = ".$user_id." AND c.`next_set_timestamp` <= '" . $timestamp . "'");
            if(!empty($schedules))
                foreach($schedules as $schedule)
                {
                    $this->exec_cron($schedule['id'],$timestamp);
                }

            $queues = $this->db->select("SELECT q.id FROM ".DB_TABLE_PREFIX."schedules_queue q WHERE q.user_id = '".$user_id."' AND q.status = 1 AND q.set_datetime <= '".$timestamp."'");
            if(!empty($queues))
                foreach($queues as $queue)
                {
                    $this->set_queue_comment($queue['id']);
                }

            $queues = $this->db->select("SELECT q.id FROM ".DB_TABLE_PREFIX."schedules_queue q WHERE q.user_id = '".$user_id."' AND q.status = 2 AND q.del_datetime <= '".$timestamp."' AND q.del_datetime > 0");
            if(!empty($queues))
                foreach($queues as $queue)
                {
                    $this->del_queue_comment($queue['id']);
                }

        }

        //echo "<br>end time: ".time()."<br>";
        echo "CRON DONE \n";
    }

    private function exec_cron($id, $timestamp)
    {
        $schedule = $this->db->selectOne("SELECT c.* FROM ".DB_TABLE_PREFIX."schedules c WHERE c.`status` = 1 AND c.next_set_timestamp <= ".$timestamp." AND c.id = '".$id."'");
        $status = 1;

        if(empty($schedule)) return false;

        if($schedule['condition_type'] == 2){
            $posts = json_decode(html_entity_decode($schedule['posts']));
            foreach($posts as $post)
            {
                $result_posts['main'][] = $post;
            }
        }

        if ($schedule['condition_type'] == 1) {
            $pages = json_decode(html_entity_decode($schedule['pages']));

            if (!empty($pages))
                foreach ($pages as $page) {
                    $created = null;
                    $post_id = false;
                    $only_owners = $schedule['source_type'] == 1;
                    $posts = $this->facebook->getObjectPosts($page, $schedule['fb_token'], 1, $only_owners);

                    if (!empty($posts))
                        foreach ($posts as $post)
                            if (strtotime($post->created_time) > strtotime($created)) {
                                $post_id = $post->id;
                                $created = $post->created_time;
                            }

                    if ($post_id) {
                        $result_posts[$page][] = $post_id;
                    }
                }
        }

        if ($schedule['condition_type'] == 3) {
            $pages = json_decode(html_entity_decode($schedule['pages']));
            $result_posts = array();
            if (!empty($pages))
                foreach ($pages as $page) {
                    $posts = $this->facebook->getObjectPosts($page, $schedule['fb_token'], 100, false);
                    if (!empty($posts)) {
                        foreach ($posts as $post) {
                            $check_exists = $this->db->selectOne("SELECT * FROM ".DB_TABLE_PREFIX."schedules_queue s WHERE s.schedule_id = '".$schedule['id']."' AND s.post_id = '".$post->id."'");
                            if(empty($check_exists)) {
                                $check = $this->check_keyword($post->message, $schedule['keyword']);
                                if ($check)
                                    $result_posts[$page][] = $post->id;
                            }
                        }
                    }
                }
        }

        $set_timestamp = $schedule['next_set_timestamp'];
        if (!empty($result_posts))
            foreach ($result_posts as $page) {
                if (!empty($page))
                    foreach ($page as $post_id) {
                        $del_timestamp = 0;
                        if ($schedule['auto_delete'] == 1) {
                            if ($schedule['delete_type'] == 1)
                                $del_timestamp = $set_timestamp + $schedule['delete_interval'];
                            else
                                $del_timestamp = $schedule['delete_timestamp'];
                        }

                        $page_id = explode('_', $post_id);
                        if (!empty($page_id[0]))
                            $page_id = $page_id[0];
                        else
                            $page_id = "";

                        $ins_data['schedule_id']    = $schedule['id'];
                        $ins_data['status']         = 1;
                        $ins_data['user_id']        = $schedule['user_id'];
                        $ins_data['set_datetime']   = $set_timestamp;
                        $ins_data['del_datetime']   = $del_timestamp;
                        $ins_data['page_id']        = $page_id;
                        $ins_data['post_id']        = $post_id;

                        $this->db->insert(DB_TABLE_PREFIX.'schedules_queue',$ins_data);
                    }
            }

        $status = 1;
        $next_set_timestamp = $set_timestamp;

        if($schedule['is_repeat'] == 0){
            $status = 2;
        }else{
            $next_set_timestamp = $this->get_next_timestamp($schedule['id'], $timestamp);
            if($next_set_timestamp >= $schedule['end_timestamp'])
                $status = 2;
        }

        $upd_data['next_set_timestamp'] = $next_set_timestamp;
        $upd_data['status']             = $status;
        $this->db->update(DB_TABLE_PREFIX.'schedules',$upd_data,$schedule['id']);
    }

    private function set_queue_comment($queue_id)
    {
        $queue = $this->db->selectOne("SELECT q.post_id, q.page_id, u.fb_token, u.fb_user_id, s.comment, s.condition_type, s.add_condition, s.keyword, q.schedule_id, q.del_datetime, s.source_type FROM ".DB_TABLE_PREFIX."schedules_queue q JOIN ".DB_TABLE_PREFIX."schedules s ON s.id = q.schedule_id JOIN ".DB_TABLE_PREFIX."users u ON u.id = s.user_id WHERE q.id = '".$queue_id."'");

        if(empty($queue))
            return false;

        $set_comment = false;
        if($queue['condition_type'] == 3 || $queue['add_condition'] == 1){
            $set_comment = true;
        }

        if($set_comment) {
            $comment = $this->make_comment($queue['comment']);
            if($queue['source_type'] == 1)
                $page_token = $this->facebook->get_page_token($queue['fb_user_id'], $queue['fb_token'], $queue['page_id']);
            else
                $page_token = $queue['fb_token'];

            $comment_id = $this->facebook->set_comment($queue['post_id'], $page_token, $comment, $queue_id);
            if ($comment_id) {
                if ($queue['del_datetime'] > 0)
                    $status = 2;
                else
                    $status = 3;

                $upd_data['status'] = $status;
                $upd_data['error'] = '';
                $this->db->update(DB_TABLE_PREFIX . 'schedules_queue', $upd_data, $queue_id);

                $ins_data['schedule_id'] = $queue['schedule_id'];
                $ins_data['comment'] = $comment;
                $ins_data['queue_id'] = $queue_id;
                $ins_data['fb_comment_id'] = $comment_id;
                $this->db->insert(DB_TABLE_PREFIX . 'completed', $ins_data);
            }
        }else{
            $owner_id = ($queue['source_type'] == 1) ? $queue['page_id'] : $queue['fb_user_id'];
            $comments = $this->facebook->getComments($queue['post_id'], $queue['fb_token'], $owner_id);

            if($queue['source_type'] == 1)
                $page_token = $this->facebook->get_page_token($queue['fb_user_id'], $queue['fb_token'], $queue['page_id']);
            else
                $page_token = $queue['fb_token'];

            $comm = $this->make_comment($queue['comment']);

            $can_comment = 1;
            if(!empty($comments)){
                foreach ($comments as $comment) {
                    if(!$comment->can_comment){
                        $can_comment = 0;
                        continue;
                    }

                    $can_comment = 1;
                    $check = $this->check_keyword($comment->message, $queue['keyword']);

                    if ($check) {
                        $exists = $this->db->selectOne("SELECT * FROM ".DB_TABLE_PREFIX."completed c WHERE c.schedule_id = '".$queue['schedule_id']."' AND c.parrent_comment_id = '".$comment->id."'");
                        if(empty($exists)) {
                            $result_comms[] = $comment->id;
                        }
                    }
                }

                $error = false;
                if(!empty($result_comms)){

                    foreach($result_comms as $comment){
                        $comment_id = $this->facebook->set_comment($comment, $page_token, $comm, $queue_id);

                        if($comment_id){
                            $ins_data = array();
                            $ins_data['schedule_id'] = $queue['schedule_id'];
                            $ins_data['comment'] = $comm;
                            $ins_data['queue_id'] = $queue_id;
                            $ins_data['fb_comment_id']  = $comment_id;
                            $ins_data['parrent_comment_id'] = $comment;
                            $this->db->insert(DB_TABLE_PREFIX.'completed',$ins_data);
                        }
                        else{
                            $error = true;
                        }
                    }
                }

                if ($queue['del_datetime'] > 0)
                    $status = 2;
                else
                    $status = 3;

                $upd_data = array();
                $upd_data['status']         = $status;
                $upd_data['can_comment']    = $can_comment;
                if(!$error) $upd_data['error']  = '';

                $this->db->update(DB_TABLE_PREFIX.'schedules_queue',$upd_data,$queue_id);
            }
        }
    }

    private function make_comment($comment)
    {
        $matches = array();
        $pattern = '/\{(.*?)\}/';
        preg_match_all($pattern,$comment,$matches);
        if(!empty($matches[1]))
        {
            $result = array();
            $patterns = array();
            foreach($matches[1] as $match){
                $match = explode('|',$match);
                $result[] = $match[rand(0,count($match) - 1)];
                $patterns[] = $pattern;
            }

            $comment = preg_replace($patterns,$result,$comment,1);
        }

        return $comment;
    }

    private function del_queue_comment($queue_id)
    {
        $queue = $this->db->selectOne("SELECT q.page_id, u.fb_user_id, c.parrent_comment_id, u.fb_token, c.fb_comment_id, s.source_type FROM ".DB_TABLE_PREFIX."schedules_queue q JOIN ".DB_TABLE_PREFIX."schedules s ON q.schedule_id = s.id JOIN ".DB_TABLE_PREFIX."users u ON u.id = q.user_id JOIN ".DB_TABLE_PREFIX."completed c ON c.queue_id = q.id WHERE q.id = '".$queue_id."' AND q.status = 2");

        if(empty($queue))
            return false;

        if($queue['source_type'] == 1)
            $page_token = $this->facebook->get_page_token($queue['fb_user_id'], $queue['fb_token'], $queue['page_id']);
        else
            $page_token = $queue['fb_token'];

        $result = $this->facebook->delete_comment($queue['fb_comment_id'], $page_token);

        $upd_data['status'] = 3;
        $this->db->update(DB_TABLE_PREFIX.'schedules_queue',$upd_data,$queue_id);
    }

    private function get_next_timestamp($schedule_id, $timestamp)
    {
        $schedule = $this->db->selectOne("SELECT * FROM ".DB_TABLE_PREFIX."schedules WHERE id = '".(int)$schedule_id."'");

        if(empty($schedule))
            return $timestamp;

        if($schedule['repeat_frequency'] == 1)
            $timestamp = $timestamp + 60*60*24;

        if($schedule['repeat_frequency'] == 3)
        {
            $timestamp = mktime(date('H',$timestamp),date('i',$timestamp),0,date('m',$timestamp)+1,date('d',$timestamp),date('Y',$timestamp));
        }


        if($schedule['repeat_frequency'] == 4)
            $timestamp = $timestamp + $schedule['repeat_interval'];

        if($schedule['repeat_frequency'] == 2)
        {
            $day = date('w',$timestamp);
            $day = $day + 1;
            $next_day = 0;
            $weekdays = json_decode(html_entity_decode($schedule['repeat_weekdays']));
            if(!empty($weekdays))
            {
                foreach($weekdays as $n_day)
                {
                    if($n_day > $day && $next_day == 0)
                        $next_day = $n_day;
                }

                if($next_day == 0)
                    $next_day = $weekdays[0];

                $add_days = ($next_day - $day > 0) ? ($next_day - $day) : (7 + $next_day - $day);

                $timestamp = $timestamp + 60*60*24*$add_days;
            }
        }

        return $timestamp;
    }

    private function check_keyword($message, $keyword, $match_all = false)
    {
        $message = strtolower($message);
        $keyword = strtolower($keyword);

        $keywords = explode(',',$keyword);
        $result = $match_all;

        if(!empty($keywords))
        {
            foreach($keywords as $keyword)
            {
                $keyword = trim($keyword);
                $check = $this->check_keyword_exists($message, $keyword);
                if($match_all)
                    $result = ($result & $check);
                else
                    $result = ($result || $check);
            }
        }else{
            return false;
        }

        return $result;
    }

    private function check_keyword_exists($message, $keyword)
    {
        if(preg_match('/^'.strtolower($keyword).'[\W]/',strtolower($message)))
            return true;

        if(preg_match('/^'.strtolower($keyword).'$/',strtolower($message)))
            return true;

        if(preg_match('/[\W]'.strtolower($keyword).'[\W]/',strtolower($message)))
            return true;

        if(preg_match('/[\W]'.strtolower($keyword).'$/',strtolower($message)))
            return true;

        return false;
    }
}