<?php

include __DIR__."/Database.php";

class Main
{
    private $con_dist;
    private $dbc;

    public function __construct()
    {
        $this->dbc = new Database();

        $dist = $this->dbc->conDist();

        if ($dist instanceof mysqli) {
            $this->con_dist = $dist;
        }
    }


    public function getUserQuota($user_id)
    {
        $u_quota = "";
        $con_user = $this->dbc->conRankUser();

        $qry = "SELECT SUM(p.auditors) as auditor_count FROM am_access a LEFT JOIN rankmoz_packages p ON a.product_id = p.package_id WHERE user_id = $user_id AND begin_date <= CURRENT_DATE AND expire_date >= CURRENT_DATE";

        if($chk = mysqli_query($con_user, $qry)) {
            if(mysqli_num_rows($chk)) {
                $res = mysqli_fetch_assoc($chk);
                $this->userRenewed($user_id, $res['auditor_count']);
            }
        } else {
            // $this->common->logErrorFatal('', "service:$qry", mysqli_error($con_user), print_r(error_get_last(), true));
        }
    }


    /**
     * Service to renew an expired user in Website Auditor
     *
     * Accepts GET params only
     *
     * @param user_id
     * @param total_quota
     * @param action=renew_user
     *
     * Return Value:
     *   JSON encoded array,
     *   VALUES:
     *     response: response message
     *     response_code: 100(success)/101(error)
     */
    public function userRenewed($user_id, $total_quota)
    {
        $rows = array();
        $valid_ids = array();
        $all_ids = array();
        $quota_used = 0;

        $qry = "SELECT id,pages_to_crawl FROM projects WHERE user_id=$user_id ORDER BY expired";
        if($chk = mysqli_query($this->con_dist, $qry)) {
            if(mysqli_num_rows($chk)) {
                while ($res = mysqli_fetch_assoc($chk)) {
                    $all_ids[] = $res['id'];
                    $rows[] = $res;
                }
            }
        } else {
            // $this->common->logErrorFatal('', "service:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }

        if(!empty($rows)) {
            foreach ($rows as $e_row) {
                $quota_used += $e_row['pages_to_crawl'];
                if($quota_used <= $total_quota) {
                    $valid_ids[] = $e_row['id'];
                }
            }
        }

        $pause_ids = array_diff($all_ids, $valid_ids);

        if(!empty($pause_ids)) {
            $qry = "UPDATE projects SET expired=2 WHERE id IN (".implode(",", $pause_ids).")";
            if(!mysqli_query($this->con_dist, $qry)) {
                // $this->common->logErrorFatal('', "service:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
            }
        }


        if(!empty($valid_ids)) {
            $qry = "UPDATE projects SET expired=0 WHERE id IN (".implode(",", $valid_ids).")";
            if(!mysqli_query($this->con_dist, $qry)) {
                // $this->common->logErrorFatal('', "service:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
            }
        }
    }



    public function getAllRankUsers()
    {
        $result = array();

        $con_user = $this->dbc->conRankUser();

        $qry = "SELECT DISTINCT a.user_id FROM am_access a LEFT JOIN rankmoz_packages p ON a.product_id = p.package_id WHERE begin_date <= CURRENT_DATE AND expire_date >= CURRENT_DATE";
        if($chk = mysqli_query($con_user, $qry)) {
            if(mysqli_num_rows($chk)) {
                while($res = mysqli_fetch_assoc($chk)) {
                    $result[] = $res['user_id'];
                }
            } else {
                $this->logErrorFatal('', "mysql:$qry", "no users found in rankwatch", print_r(error_get_last(), true));
            }
        } else {
            $this->logErrorFatal('', "mysql:$qry", mysqli_error($con_user), print_r(error_get_last(), true));
        }
        return $result;
    }



    public function getAllAuditorUsers()
    {
        $result = array();

        $qry = "SELECT DISTINCT user_id FROM projects";
        if($chk = mysqli_query($this->con_dist, $qry)) {
            if(mysqli_num_rows($chk)) {
                while($res = mysqli_fetch_assoc($chk)) {
                    $result[] = $res['user_id'];
                }
            } else {
                $this->logErrorFatal('', "mysql:$qry", "no users found in auditor", print_r(error_get_last(), true));
            }
        } else {
            $this->logErrorFatal('', "mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }
        return $result;
    }


    public function pauseExpiredUsers($uids)
    {
        if(!empty($uids)) {
            $qry = "UPDATE projects set expired=1 WHERE user_id IN (".implode(",", $uids).") AND expired=0";
            if(!mysqli_query($this->con_dist, $qry)) {
                $this->logErrorFatal('', "mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
            }
        }
    }

    public function resumeExpiredUsers($uids)
    {
        if(!empty($uids)) {
            $qry = "UPDATE projects set expired=0 WHERE user_id IN (".implode(",", $uids).") AND expired=1";
            if(!mysqli_query($this->con_dist, $qry)) {
                $this->logErrorFatal('', "mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
            }
        }
    }


   public function getAllRankProjs()
    {
        $con_proj = $this->dbc->conRankProj();

        $result = array();

        $qry = "SELECT p_id,domain_name,member_id FROM projects2";
        if($chk = mysqli_query($con_proj, $qry)) {
            if(mysqli_num_rows($chk)) {
                while($res = mysqli_fetch_assoc($chk)) {
                    if(!empty($res['domain_name']) && !empty($res['p_id'])) {
                        $row = array();
                        $row['domain'] = $res['domain_name'];
                        $row['user_id'] = $res['member_id'];
                        $result[$res['p_id']] = $row;
                    }
                }
            } else {
                $this->logErrorFatal('', "mysql:$qry", "no projects found in rankwatch", print_r(error_get_last(), true));
            }
        } else {
            $this->logErrorFatal('', "mysql:$qry", mysqli_error($con_proj), print_r(error_get_last(), true));
        }
        return $result;
    }


   public function getAllAuditorProjs()
    {
        $result = array();

        $qry = "SELECT id,id_hash,domain,user_id FROM projects";
        if($chk = mysqli_query($this->con_dist, $qry)) {
            if(mysqli_num_rows($chk)) {
                while($res = mysqli_fetch_assoc($chk)) {
                    $row = array();
                    $row['domain'] = $res['domain'];
                    $row['user_id'] = $res['user_id'];
                    $row['id'] = $res['id'];
                    $result[$res['id_hash']] = $row;
                }
            } else {
                $this->logErrorFatal('', "mysql:$qry", "no projects found in auditor", print_r(error_get_last(), true));
            }
        } else {
            $this->logErrorFatal('', "mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }
        return $result;
    }


    public function insertNewProj($id_hash, $domain, $user_id)
    {
        // if($this->chkDomainExists($domain)) {
        //     $qry = "INSERT INTO projects (id_hash,user_id,domain,pages_to_crawl,crawled,scraped,processed,duplicated,history_created,dump_deleted,status,last_crawled_on,first_crawled_on,dup_running) VALUES ('".$id_hash."', $user_id, '".$domain."', 250, 2, 2, 2, 2, 2, 2, 2, NOW(), NOW(), 1)";
        // } else {
        //     $qry = "INSERT INTO projects (id_hash,user_id,domain,pages_to_crawl) VALUES ('".$id_hash."', $user_id, '".$domain."', 250)";
        // }

        $qry = "INSERT INTO projects (id_hash,user_id,domain,pages_to_crawl) VALUES ('".$id_hash."', $user_id, '".$domain."', 250)";
        if(!mysqli_query($this->con_dist, $qry)) {
            $this->logErrorFatal('', "mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }
    }


    public function chkDomainExists($domain)
    {
        $qry = "SELECT id FROM projects WHERE domain='".$domain."' AND dup_running=0 AND pages_crawled > 0";
        if($chk = mysqli_query($this->con_dist, $qry)) {
            if(mysqli_num_rows($chk)) {
                return true;
            } else {
                return false;
            }
        } else {
            $this->logErrorFatal('', "mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }
        return false;
    }



    public function delProject($pid, $domain)
    {
        $qry = "SELECT * FROM projects WHERE id=$pid";
        if($chk = mysqli_query($this->con_dist, $qry)) {
            $res = mysqli_fetch_assoc($chk);
            // if($res['crawled'] != 2 || $res['scraped'] != 2 || $res['processed'] != 2 || $res['duplicated'] != 2 || $res['history_created'] != 2) {
            //     $result = array(
            //         'response' => "Project is currently processing, please wait until it's finished.",
            //         'response_code' => 101
            //     );
            //     return json_encode($result);
            // }
            $pid = $res['id'];

            if(!empty($pid)) {
                $del = "DELETE FROM projects WHERE id=$pid";
                if(mysqli_query($this->con_dist, $del)) {
                    if($res['dup_running'] == 0) {
                        $this->delProjMongo($pid);
                        // $this->chkDupProjs($pid, $res['domain']);
                    }

                    $result = array(
                        'response' => "Project successfully deleted.",
                        'response_code' => 100
                    );
                    return json_encode($result);
                } else {
                    // $this->common->logErrorFatal('', 'mysql:', mysqli_error($this->con_dist), print_r(error_get_last(), true));
                }
            }
        } else {
            // $this->common->logErrorFatal('', 'mysql:', mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }
    }


    public function delProjMongo($pid)
    {
        $mongo = $this->dbc->conMongo();
        if (!is_object($mongo)) {
            // $this->common->logErrorFatal('', 'mongo:', 'mongo connection object is unusable'.print_r($mongo, true), print_r(error_get_last(), true));
            return;
        }

        if(!empty($pid)) {
            $pid = (int)$pid;

            $mongo->auditor->remove(array('pi' => $pid));
            $mongo->auditor_nonindex->remove(array('pi' => $pid));
            $mongo->auditor_non200->remove(array('pi' => $pid));
            $mongo->auditor_failed->remove(array('pi' => $pid));
        }
    }


    public function chkDupProjs($pid, $domain)
    {
        $qry = "SELECT id,pages_to_crawl,dup_running,crawl_no FROM projects WHERE domain='".$domain."' AND id != '".$pid."' AND expired=0  ORDER BY pages_to_crawl DESC LIMIT 1";
        if($chk = mysqli_query($this->con_dist, $qry)) {
            if(mysqli_num_rows($chk)) {
                $res = mysqli_fetch_assoc($chk);

                if($res['dup_running'] == 1) {
                    $this->markNominee($res['id'], $domain);
                }
            }
        } else {
            // $this->common->logErrorFatal('', 'mysql:', mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }
    }


    public function markNominee($pid, $domain)
    {
        $qry = "UPDATE projects SET runnow=1,crawled=0,scraped=0,processed=0,duplicated=0,history_created=0,dump_deleted=0,status=0,last_crawled_on=NOW(),dup_running=0,last_crawled_on=NULL WHERE domain='".$domain."' AND id = $pid";
        if(mysqli_query($this->con_dist, $qry)) {
            $qry2 = "UPDATE projects SET crawled=2,scraped=2,processed=2,duplicated=2,history_created=2,dump_deleted=2,status=2,last_crawled_on=NOW(),dup_running=1 WHERE id != $pid AND domain='".$domain."'";
            if(!mysqli_query($this->con_dist, $qry2)) {
                // $this->common->logErrorFatal('', 'mysql:', mysqli_error($this->con_dist), print_r(error_get_last(), true));
            }
        } else {
            // $this->common->logErrorFatal('', 'mysql:', mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }
    }


    // public function delExtraProjs($pid, $domain)
    // {
    //     if(!empty($pid)) {
    //         $this->delProjMongo($pid);

    //         $qry = "DELETE FROM projects WHERE id = $pid";
    //         if(mysqli_query($this->con_dist, $qry)) {
    //             return true;
    //         } else {
    //             $this->logErrorFatal('', "mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
    //         }
    //     }
    // }

    public function getFile($json_dir)
    {
        $dir = opendir($json_dir);
        while (false !== ($entry = readdir($dir))) {

            if($entry != '.' && $entry != '..' && preg_match('/(.json)$/', $entry)) {
                return $entry;
            }
        }
    }

    public function importJsonFile($json_dir, $json_file, $collection, $try="")
    {
        $err_dir = "/var/www/html/jsons_error/";

        $f_check = file($json_dir.$json_file);
        for ($i = count($f_check)-1; $i < count($f_check); $i++) {
            if($f_check[$i] == "mongoimportend") {
                unset($f_check[$i]);

                $fp = fopen($json_dir.$json_file, 'w');
                fwrite($fp, implode('', $f_check));
                fclose($fp);

                $run = "mongoimport --db distributed --collection $collection --file ".$json_dir.$json_file." --type json --host 127.0.0.1 2>&1";

                exec($run, $output, $errors);

                if (!empty($errors)) {
                    if (empty($try)) {
                        $try = 0;
                    }

                    $try += 1;
                    if($try < 2) {
                        $fo = fopen($json_dir.$json_file, "r");
                        $f_content = "";
                        while($line = fgets($fo)) {
                            if(json_decode($line)) {
                                $f_content .= $line;
                            }
                        }
                        file_put_contents($json_dir.$json_file, $f_content);
                        $this->importJsonFile($json_dir, $json_file, $collection,$try);
                    }

                    $this->logErrorFatal('', "mongoimport:$run", 'error code:'.$errors, print_r($output, true));
                    if(!is_dir($err_dir)) {
                        mkdir($err_dir);
                    }
                    rename($json_dir.$json_file, $err_dir.time()."_$json_file");
                } else {
                    unlink($json_dir.$json_file);
                }
            } else {
                unlink($json_dir.$json_file);
            }
        }
        // $this->checkProjCompleted($json_file, $json_dir);
    }


    // public function checkProjCompleted($file_name, $json_dir)
    // {
    //     $file_arr = explode('_', $file_name);
    //     $pid = $file_arr[2];

    //     $qry = "SELECT crawled,scraped,processed FROM projects WHERE id=$pid";
    //     if($chk = mysqli_query($this->con_dist, $qry)) {
    //         if(mysqli_num_rows($chk)) {
    //             $row = mysqli_fetch_assoc($chk);
    //             if($row['crawled'] == 2 && $row['scraped'] == 2 && $row['processed'] == 2) {
    //                 $file_to_check = $file_arr[0]."_".$file_arr[1]."_".$file_arr[2];
    //                 $this->chkMongoFinished($file_to_check, $json_dir, $pid);
    //             }
    //         }
    //     } else {
    //         $this->logErrorFatal('', "mongoimport mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
    //     }
    // }


    public function chkMongoFinished($pid, $domain, $data_dir, $failed_dir, $non200_dir, $nonindex_dir)
    {
        $completed = 1;
        $json_data_dir = $data_dir.$domain."_data_".$pid."_*";
        $json_failed_dir = $failed_dir.$domain."_failed_".$pid."_*";
        $json_non200_dir = $non200_dir.$domain."_non200_".$pid."_*";
        $json_nonindex_dir = $nonindex_dir.$domain."_nonindex_".$pid."_*";

        $files_data = glob($json_data_dir);
        $files_failed = glob($json_failed_dir);
        $files_non200 = glob($json_non200_dir);
        $files_nonindex = glob($json_nonindex_dir);
        if(!empty($files_data) || !empty($files_failed) || !empty($files_non200) || !empty($files_nonindex)) {
            $completed = 0;
        }

        if($completed == 1) {
            $qry = "UPDATE projects SET mongo_imported=2 WHERE id=$pid";
            if(!mysqli_query($this->con_dist, $qry)) {
                $this->logErrorFatal('', "mongoimport mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
            } else {
                // $this->logErrorFatal('', "mongoimport mysql completed:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
            }
        }
    }


    public function chkMongoFinishError($data_dir, $failed_dir, $non200_dir, $nonindex_dir)
    {
        $qry = "SELECT id,domain FROM projects WHERE crawled=2 AND processed=2 AND mongo_imported=0 AND history_created=0";
        if($chk = mysqli_query($this->con_dist, $qry)) {
            if(mysqli_num_rows($chk)) {
                $row = mysqli_fetch_assoc($chk);
                $this->chkMongoFinished($row['id'], $row['domain'], $data_dir, $failed_dir, $non200_dir, $nonindex_dir);
            }
        } else {
            $this->logErrorFatal('', "mongoimport mysql:$qry", mysqli_error($this->con_dist), print_r(error_get_last(), true));
        }
    }

    public function logErrorFile($err)
    {
        $dir = '/var/www/html/logs/';
        $file = '/var/www/html/logs/error.log';

        if (!is_dir($dir)) {
            mkdir($dir);
        }
        $error = $err.print_r(error_get_last(), true).print_r(debug_backtrace(0), true);
        $fhn = fopen($file, 'a+');
        fwrite($fhn, $error."\n");
        fclose($fhn);
    }

    /**
     *  Function: logs custom erros in DB and provides front end error managment.
     *
     *  @param $uid: logged in user id
     *  @param $section: section where error occured, (file,mysql,etc)
     *  @param $cause: detaild error reporting, mostly error_get_last() output
     *  @param $mongoDB: mongoDB connection resource
     */
    public function logErrorFatal($pid, $section, $cause, $detail = '')
    {
        $log = "INSERT INTO log_fatal VALUES('', '".$pid."','".addslashes($section)."','".addslashes($cause)."', NOW(), '".addslashes(trim(preg_replace('/\s+/', ' ', $detail)))."',4, '".addslashes(trim(preg_replace('/\s+/', ' ', print_r(debug_backtrace(0), true))))."')";

        if (mysqli_query($this->con_dist, $log)) {
            return true;
        } else {
            // $this->logErrorFile(print_r(array($pid, $section, $cause, $detail, mysqli_error($this->con_dist)), true));

            return mysqli_error($this->con_dist);
        }
    }

}
