<?php

class RM_Chronos {    
    
    const TASKS_TABLE = 'rm_tasks';
    const RULES_TABLE = 'rm_rules';
    const TASK_EXE_LOG = 'rm_task_exe_log';
    const CRON_INTERVAL = 3600;
    protected static $base_dir, $base_url;
    
    public static function init() {
        self::$base_dir = plugin_dir_path(plugin_dir_path(__FILE__)); 
        self::$base_url = plugin_dir_url(plugin_dir_path(__FILE__));    
        self::attach_hooks();
        //schedule cron
        /*if ( ! wp_next_scheduled( 'rm_chronos_task_exe_hook' ) ) {
            //wp_schedule_event( time(), 'rm_automation_interval', 'rm_chronos_task_exe_hook' );
        }*/
    }
    
    public static function get_base_dir() {
        return self::$base_dir;    
    }
    
    public static function get_base_url() {
        return self::$base_url;    
    }
    
    public static function activate() {
        self::create_tables();
    }
    
    public static function deactivate() {
        //remove cron job here
        //die("death is smiling at upon us all.");
    }
    
    
    public static function make_cron_actions($task_id = null, $tasks = null){
        if(isset($task_id) && !empty($task_id)){
            self::schedule_cron($task_id);
        }else{
            //$tasks = self::get_tasks(null, 'active');
            foreach($tasks as $task) { 
                self::schedule_cron($task->task_id);
            }
        }
    }
    public static function schedule_cron($task_id){
        $service = new RM_Chronos_Service;
        $task_factory = new RM_Chronos_Task_Factory();
        $task = $task_factory->create_task($task_id);
        if(isset($task->meta['rmc_task_type']) && $task->meta['rmc_task_type'] == 'automatic' && $task->is_active ):
            if(isset($task->meta['rmc_task_first_execution']) && isset($task->meta['rmc_task_schedule'])):
                $task_cron_name = 'rm_automation_task_'.$task->task_id;
                $first_execution = isset($task->meta['rmc_task_first_execution']) ? $task->meta['rmc_task_first_execution'] : time();
                $reccurence = isset($task->meta['rmc_task_schedule']) ? $task->meta['rmc_task_schedule'] : 'daily';
                if ( ! wp_next_scheduled( $task_cron_name , array($task->task_id)) && $service->get_cron_name($task_cron_name) == false ) {
                   wp_schedule_event( $first_execution, $reccurence, $task_cron_name, array($task->task_id), true );
                  
                }
            endif;
        endif;
        self::cron_schedule_callback($task);
    }
    
    public static function cron_schedule_callback($task = null){
        //$tasks = self::get_tasks(null, 'active');    
        //$task_factory = new RM_Chronos_Task_Factory();
        //foreach($tasks as $task) {            
            //$task = $task_factory->create_task($task->task_id);
            if(isset($task->meta['rmc_task_type']) && $task->meta['rmc_task_type'] == 'automatic' && $task->is_active ):
                add_action( 'rm_automation_task_'.$task->task_id, 'RM_Chronos::excecute_cron_jobs',10,1);
            endif;
        //}
    }
    
    public static function excecute_cron_jobs($task_id){ 
        $task_factory = new RM_Chronos_Task_Factory();
        $task = $task_factory->create_task($task_id);
        if($task instanceof RM_Chronos_Task){
            $task->execute();
        }
         
    }
    public static function attach_hooks() {
        add_action("rm_admin_menu_after_field_stats", "RM_Chronos::add_admin_pages");
        add_action("rm_per_site_tables_created", "RM_Chronos::create_tables");
        add_action("rm_migration_finished", "RM_Chronos::db_migrate");
        add_action("registrationmagic_deactivated", "RM_Chronos::deactivate");
        //add_action("plugins_loaded", "RM_Chronos::hooked_init");
        add_action("init", "RM_Chronos::hooked_init");
        add_filter('cron_schedules', 'RM_Chronos::add_cron_interval');
        add_action('rm_chronos_task_exe_hook', 'RM_Chronos::run_tasks');
        add_action('wp_ajax_rm_chronos_ajax', 'RM_Chronos::handle_ajax_req');
        add_action("rm_form_settings_dashboard_action_icon", "RM_Chronos::add_rm_form_setting_menu");
        add_action('media_buttons', 'RM_Chronos::add_field_dropdown_to_editor');
        add_action("rm_formcard_menu_action_icon", "RM_Chronos::add_rm_formcard_menu", 10, 2);
        //add_action("update_edit_delete_cron", "RM_Chronos_Task_Controller::update_edit_delete_cron", 10, 2);
    }

    public static function hooked_init($network_wide) {
        $tasks = self::get_tasks(null, 'active');
        self::make_cron_actions(null, $tasks);
        //self::cron_schedule_callback($tasks);
    }
    
    public static function add_cron_interval($schedules) {
        $schedules['rm_automation_interval'] = array(
            'interval' => self::CRON_INTERVAL,
            'display'  => __("RM Automation Interval",'custom-registration-form-builder-with-submission-manager'),
        );
        
        $schedules['5_min'] = array(
            'interval' => 720,
            'display'  => __("RM 5 Min",'custom-registration-form-builder-with-submission-manager'),
        );
        return $schedules;
    }
    
    public static function add_admin_pages($value)
    {
        $menu_title = __('Automation','custom-registration-form-builder-with-submission-manager');     
        $rm_automation_intro_time = get_site_option('rm_option_automation_intro_time', null);
        $thirty_days = 30*24*3600;
        
        if(!$rm_automation_intro_time) {
            $rm_automation_intro_time = time();
            update_site_option('rm_option_automation_intro_time', $rm_automation_intro_time);
        }
        
        if((time() - (int)$rm_automation_intro_time) <= $thirty_days )
            $menu_title .= "";
        add_submenu_page("rm_form_manage",__('Automation','custom-registration-form-builder-with-submission-manager'), $menu_title, $value."manage_options", "rm_ex_chronos_manage_tasks",  "RM_Chronos::handle_request" );
        add_submenu_page("rm_dummy_string", __("RM Chronos 3", 'custom-registration-form-builder-with-submission-manager'), __('RM Chronos 3','custom-registration-form-builder-with-submission-manager'), $value."manage_options", "rm_ex_chronos_edit_task",  "RM_Chronos::handle_request" );
    }
    
    public static function db_migrate() {
        //self::create_tables();
        $existing_db_version = get_site_option("rm_option_ex_chronos_db_version", false);
        
        if(!$existing_db_version) {
            update_site_option("rm_option_ex_chronos_db_version", RM_CHRONOS_DB_VERSION);
            return "chronos_fresh_install";
        }
        
        if($existing_db_version && floatval($existing_db_version) >= RM_CHRONOS_DB_VERSION) {
            return "chronos_better_or_equal";
        }
        
        //perform migration
        update_site_option("rm_option_ex_chronos_db_version", RM_CHRONOS_DB_VERSION);
    }
    
    public static function get_table_name_for($identifier) {
        global $wpdb;
        $prefix = $wpdb->prefix;
        $table_name = null;
        switch($identifier) {
            case 'TASKS':            
                $table_name = $prefix.self::TASKS_TABLE;
                break;
            case 'RULES':
                $table_name = $prefix.self::RULES_TABLE;
                break;
            case 'TASK_EXE_LOG':
                $table_name = $prefix.self::TASK_EXE_LOG;
                break;
        }
        return $table_name;
    }
    
    public static function create_tables() {
        global $wpdb;
        $table_name = $wpdb->prefix.self::TASKS_TABLE;
        if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)
        {
            //Ensures proper charset support. Also limits support for WP v3.5+.
            $charset_collate = $wpdb->get_charset_collate();

            $sql = "CREATE TABLE $table_name (
                    `task_id` INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                    `form_id` INT(6),
                    `name` VARCHAR(255),
                    `desc` VARCHAR(1000),
                    `must_rules` TEXT,
                    `any_rules` TEXT,
                    `is_active` TINYINT(1) DEFAULT 1,
                    `actions` TEXT,
                    `task_order` INT(6),
                    `meta` TEXT
                    )$charset_collate;";

            dbDelta($sql);
        }
        
        $table_name = $wpdb->prefix.self::RULES_TABLE;
        if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)
        {
            //Ensures proper charset support. Also limits support for WP v3.5+.
            $charset_collate = $wpdb->get_charset_collate();

            $sql = "CREATE TABLE $table_name (
                    `rule_id` INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                    `type` INT(6),
                    `attr_name` VARCHAR(255),
                    `attr_value` VARCHAR(1000),
                    `operator` VARCHAR(20),
                    `meta` TEXT
                    )$charset_collate;";

            dbDelta($sql);
        }
        
        $table_name = $wpdb->prefix.self::TASK_EXE_LOG;
        if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)
        {
            //Ensures proper charset support. Also limits support for WP v3.5+.
            $charset_collate = $wpdb->get_charset_collate();

            $sql = "CREATE TABLE $table_name (
                    `texe_log_id` INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                    `task_id` INT(6),
                    `action` INT(6),
                    `sub_ids` LONGTEXT,
                    `user_ids` LONGTEXT,
                    `meta` TEXT
                    )$charset_collate;";

            dbDelta($sql);
        }
    }    
    //$state = null => all tasks
    // active => only active/enabled tasks
    // inactive => only inactive/disabled tasks
    // if form_id is null, tasks for all forms are returned
    public static function get_tasks($form_id = null, $state = null) {
        global $wpdb;        
        $tasks_table = self::get_table_name_for("TASKS");
        
        $query = "SELECT * FROM {$tasks_table} WHERE ";
        
        $where_clause = array();
        
        switch($state) {
            case 'active':
                $where_clause[] = "`is_active` = 1";
                break;
            case 'inactive':
                $where_clause[] = "`is_active` = 0";
                break;
        }
        
        if($form_id)
            $where_clause[] = "`form_id` = {$form_id}";
        
        $where_clause = implode(" AND ", $where_clause);
        if(!$where_clause)
            $where_clause = "1";
        
        $res = $wpdb->get_results("SELECT * FROM {$tasks_table} WHERE {$where_clause} ORDER BY `form_id`, `task_order`, `task_id`");
        
        if(!$res || !is_array($res))
            $res = array();
        
        return $res;
    }
    
    public static function handle_request() {
        if(!isset($_REQUEST['page']))
            return;
        
        $task_controller = new RM_Chronos_Task_controller;
        $x = isset($req['rm_cron_slug']) ? sanitize_text_field($_REQUEST['rm_cron_slug']) : sanitize_text_field($_REQUEST['page']);
        $action = substr($x, strlen('rm_ex_chronos_'));
        if(is_callable(array($task_controller, $action)))
            $task_controller->$action($_REQUEST);
    }
    
    public static function run_tasks() {        
        $tasks = self::get_tasks(null, 'active');    
        $task_factory = new RM_Chronos_Task_Factory();
        foreach($tasks as $task) {            
            $task = $task_factory->create_task($task->task_id);
            if($task instanceof RM_Chronos_Task)
                $task->execute();
        }
    }
    
    protected static function run_single_task_ajax() {    
        if(isset($_POST['task_id'])) {
            $task_id = intval(sanitize_text_field($_POST['task_id']));
            $task_factory = new RM_Chronos_Task_Factory();
            $task = $task_factory->create_task($task_id);
            if($task && $task instanceof RM_Chronos_Task) {
                $task->execute();
                return json_encode(array("result"=>"done","type"=>""));
            } else {
                return json_encode(array("result"=>"error","type"=>"invalid_task_id"));
            }
        } else {
            return json_encode(array("result"=>"error","type"=>"invalid_task_id"));
        }       
    }
    
    protected static function delete_tasks_batch() {    
        if(isset($_POST['task_ids'])) {
            $task_ids = is_array($_POST['task_ids']) ? array_map('sanitize_text_field', $_POST['task_ids']) : sanitize_text_field($_POST['task_ids']);
            if(is_array($task_ids)) {
                $task_ids = self::filter_task_ids($task_ids);
                $service = new RM_Chronos_Service();
                $service->remove_tasks_batch($task_ids);
            }
        }    
    }
    
    protected static function duplicate_tasks_batch() {    
        if(isset($_POST['task_ids'])) {
            $task_ids = is_array($_POST['task_ids']) ? array_map('sanitize_text_field', $_POST['task_ids']) : sanitize_text_field($_POST['task_ids']);
            if(is_array($task_ids)) {
                $task_ids = self::filter_task_ids($task_ids);
                $service = new RM_Chronos_Service();
                $service->duplicate_tasks_batch($task_ids);
            }
        }    
    }
    
    protected static function set_state_tasks_batch() { 
        if(isset($_POST['task_ids'], $_POST['state'])) {
            $task_ids = is_array($_POST['task_ids']) ? array_map('sanitize_text_field', $_POST['task_ids']) : sanitize_text_field($_POST['task_ids']);
            if(is_array($task_ids)) {
                $task_ids = self::filter_task_ids($task_ids);
                $service = new RM_Chronos_Service();
                $service->set_state_tasks_batch($task_ids, sanitize_text_field($_POST['state']));
            }
        }    
    }
    
    protected static function update_task_order() {    
        if(isset($_POST['ordered_task_ids'])) {
            $ordered_task_ids = is_array($_POST['ordered_task_ids']) ? array_map('sanitize_text_field', $_POST['ordered_task_ids']) : sanitize_text_field($_POST['ordered_task_ids']);
            if(is_array($ordered_task_ids)) {
                $task_ids = self::filter_task_ids($ordered_task_ids);
                $service = new RM_Chronos_Service();
                $service->update_task_order($ordered_task_ids);
            }
        }    
    }
    
    public static function handle_ajax_req() {
        if(check_ajax_referer('rmc_sortable_tasks_nonce','sortable_tasks_nonce') && current_user_can('manage_options') && isset($_POST['rm_chronos_ajax_action'])) {
            
            switch(sanitize_text_field($_POST['rm_chronos_ajax_action'])) {
                case 'trigger_task':
                    echo wp_kses_post((string)self::run_single_task_ajax());
                    break;
                
                case 'delete_tasks_batch':
                    echo wp_kses_post((string)self::delete_tasks_batch());
                    break;
                
                case 'duplicate_tasks_batch':
                    echo wp_kses_post((string)self::duplicate_tasks_batch());
                    break;
                
                case 'set_state_tasks_batch':
                    echo wp_kses_post((string)self::set_state_tasks_batch());
                    break;
                
                case 'update_task_order':
                    echo wp_kses_post((string)self::update_task_order());
                    break;
            }
        }
        wp_die();
    }
    
    public static function add_rm_form_setting_menu($form_id) {
        $rm_task_manager_url = admin_url("admin.php?page=rm_ex_chronos_manage_tasks&rm_form_id={$form_id}");
        ?>
            <div class="rm-grid-icon difl" id="rm-automate-icon">
                <a href="<?php echo esc_url($rm_task_manager_url); ?>" class="rm_fd_link">    
                    <div class="rm-grid-icon-area dbfl">
                        <img class="rm-grid-icon dibfl" src="<?php echo esc_url(RM_Chronos::get_base_url()); ?>images/automation.png">
                    </div>
                    <div class="rm-grid-icon-label dbfl"><?php echo wp_kses_post((string)RM_Chronos_UI_Strings::get('LABEL_TASKS')); ?></div>
                </a>
            </div> 
        <?php
    }
    
    public static function add_rm_formcard_menu($form_id, $rdrto="") {
        $rm_task_manager_url = admin_url("admin.php?page=rm_ex_chronos_manage_tasks&rm_form_id={$form_id}&rdrto={$rdrto}");
        ?>            
            <div class="rm-formcard-tab-item">
                <a href="<?php echo esc_url($rm_task_manager_url); ?>" class="rm_fd_link">   
                    <img class="rm-formcard-icon" src="<?php echo esc_url(RM_Chronos::get_base_url()); ?>images/automation.png">
                    <div class="rm-formcard-label"><?php echo wp_kses_post((string)RM_Chronos_UI_Strings::get('LABEL_TASKS')); ?></div>
                </a>
            </div>
        <?php
    }
    
    public static function add_field_dropdown_to_editor($editor_id) {
        
        if(!is_admin() || !function_exists('get_current_screen'))
            return;
        
        $screen = get_current_screen();
        if(!$screen || $screen->id != 'admin_page_rm_ex_chronos_edit_task')
            return;
        
        $service = new RM_Chronos_Service;
        $tmp = explode("_", (string)$editor_id);
        $form_id = end($tmp);
        $fields = $service->get_all_form_fields($form_id);        
        ?>
        <select id="rmc_field_selector_task_action_send_mail">
            <option value=""><?php _e("Select a Field",'custom-registration-form-builder-with-submission-manager') ?></option>
            <?php foreach($fields as $field): 
                    echo "<option value='".esc_attr($field->field_type)."_".esc_attr($field->field_id)."'>".esc_html($field->field_label)."</option>";
                  endforeach; ?>
        </select>
        <?php
    }
    
    public static function filter_task_ids($task_ids) {
        $filtered_ids = array();
        foreach($task_ids as $id) {
            array_push($filtered_ids,intval($id));
        }
        return $filtered_ids;
    }
}
