<?php
/*
* fasta_oracle.php
* http://tasuke.dna.affrc.go.jp/
*
* Author: Ryutaro Itoh
*
* Copyright (c) 2013 National Institute of Agrobiological Sciences   
*
* This software is released under the MIT License.
*
* http://opensource.org/licenses/mit-license.php
*/

set_time_limit(1200);//20min

//From http request or command line
if (!isset($_SERVER["HTTP_HOST"])) {
    parse_str($argv[1], $_POST);
    foreach($_POST as $key => $val){
        $_POST[$key] = rtrim($val);
    }
    chdir($_POST['path']);
    set_time_limit(0);
}

require '../../conf/config.php';
////////////////////////////////// Connecting with DB
$conn = oci_connect($user, $pswd, $host."/".$db, "AL32UTF8");
if(!$conn) {
    $e = oci_error();
    error_log($e["message"]."\nConnection failed.\n");
    exit;
}

$redis;
if($useRedis == "enable"){
    $str = "";
    if($redis = new Redis()) {
        if(!$connRedis = $redis -> connect($redisHost,$redisPort)){
            error_log("Connection failed.\n");
            exit;
        }
        if(!$redis->select($redisDBName)){
            error_log("Database '".$redisDBName."' was not found.\n");
            exit;
        }
    }else{
        error_log("Can not use the PHP-Redis.\n");
        $useRedis = "disable";
    }
}

////////////////////////////////// Parameters

(isset($_POST['prm_fa_chr']) && !empty($_POST['prm_fa_chr'])) ? $prm_chr=$_POST['prm_fa_chr']:returnError("Error");
(isset($_POST['prm_fa_s']) && !empty($_POST['prm_fa_s'])) ? $prm_s=$_POST['prm_fa_s']:returnError("Error");
(isset($_POST['prm_fa_e']) && !empty($_POST['prm_fa_e'])) ? $prm_e=$_POST['prm_fa_e']:returnError("Error");
(isset($_POST['prm_fa_tgt']) && !empty($_POST['prm_fa_tgt'])) ? $prm_tgt=$_POST['prm_fa_tgt']:returnError("Error");
(isset($_POST['prm_fa_var']) && !empty($_POST['prm_fa_var'])) ? $prm_var=$_POST['prm_fa_var']:$prm_var=".";
(isset($_POST['prm_fa_qual'])) ? $prm_qual=$_POST['prm_fa_qual']:returnError("Error");
(isset($_POST['prm_fa_dp'])) ? $prm_dp=$_POST['prm_fa_dp']:returnError("Error");
(isset($_POST['prm_fa_list']) && !empty($_POST['prm_fa_list'])) ? $prm_list=$_POST['prm_fa_list'] : returnError("Error");
(isset($_POST['prm_fa_name']) && !empty($_POST['prm_fa_name'])) ? $prm_name=$_POST['prm_fa_name'] : returnError("Error");
(isset($_POST['prm_fa_nameS']) && !empty($_POST['prm_fa_nameS'])) ? $prm_nameS=$_POST['prm_fa_nameS'] : returnError("Error");
(isset($_POST['prm_fa_ref']) && !empty($_POST['prm_fa_ref'])) ? $prm_ref=$_POST['prm_fa_ref'] : returnError("Error");
(isset($_POST['prm_fa_width'])) ? $prm_width=$_POST['prm_fa_width'] : returnError("Error");
(isset($_POST['prm_fa_avd'])) ? $prm_avd=$_POST['prm_fa_avd'] : returnError("Error");
(isset($_POST['prm_fa_p3prm'])) ? $prm_p3prm=$_POST['prm_fa_p3prm'] : returnError("Error");
(isset($_POST['prm_fa_avd'])) ? $prm_avd=$_POST['prm_fa_avd'] : returnError("Error");
(isset($_POST['prm_fa_Ns'])) ? $prm_Ns=$_POST['prm_fa_Ns'] : returnError("Error");
(isset($_POST['prm_type']) && !empty($_POST['prm_type'])) ? $prm_type=$_POST['prm_type'] : returnError("Error");

if(!_validate_chrs($conn,$prm_chr)){_stopError("||Invalid value");}
if(!_validate_num($prm_qual)){_stopError("||Invalid value");}
if(!_validate_num($prm_dp)){_stopError("||Invalid value");}
if(!_validate_num($prm_width)){_stopError("||Invalid value");}
if(!_validate_num($prm_avd)){_stopError("||Invalid value");}
if(!_validate_num($prm_Ns)){_stopError("||Invalid value");}

$primer3Path_checked="";
$primer3ThermPath_checked="";
if(isset($primer3Path)){
    $primer3Path_checked=$primer3Path;
}
if(isset($primer3ThermPath)){
    $primer3ThermPath_checked=$primer3ThermPath;
}
if($prm_type != "a" && $prm_type != "b" && $prm_type != "c"){
    error_log("Invalid value: type.\n");
    exit;
}
if (isset($_SERVER["HTTP_HOST"])) {
    if($prm_e-$prm_s>19999){  // Maximum size is 20K
        $prm_e=$prm_s+19999;
    } else if($prm_e-$prm_s < 0){
        $prm_e=$prm_s;
    }
}

//////////////////////////processing
$seqname = array();
$list = explode(",",$prm_list);
if(!_validate_each_acc($list)){
    error_log("Invalid accession list.\n");
    exit;
}
$list_cp = $list;
if($useRedis == "enable"){
    $refseq = _getRefseqRedis($prm_chr, $prm_s, $prm_e, $connRedis);
}else{
    $refseq = _GETREFSEQ($prm_chr, $prm_s, $prm_e,$conn);
}
$seqname = _HEADERFA($list,$prm_s,$prm_e,$prm_name,$prm_nameS,$conn,$prm_type);
$altpos =  _VAR($list,$prm_chr,$prm_s,$prm_e,$conn,$prm_type,$seqname,$prm_dp,$prm_qual);
$pr_refseq="";

if($prm_type == "a"){//gen fasta file
    $seqname_valid = _valRefName($prm_ref,$reference);
    if($seqname_valid == 0 and isset($_SERVER["HTTP_HOST"])){
        returnError("Invalid reference name.");
        exit;
    }
    $pr_refseq = _rpl_REF("REFERENCE",$altpos,$prm_s,$prm_e,$refseq,$list_cp);
    if ($prm_width != 0){ 
        $pr_refseq = wordwrap($pr_refseq, $prm_width, "\n", true);
    }
    echo ">REF_".$prm_ref."\n";
    echo $pr_refseq."\n";
}elseif($prm_type == "b"){//gen seq for web-primer3 http://primer3.ut.ee/
    $range=explode("-",$prm_tgt);
    $start=0;
    $end=0;
    if($prm_var=="DEL"){
        $start=$range[0]-1;
        $end=$range[1]-1;
    }else{
        $start=$range[0];
        $end=$range[1];
    }
    $targetLen=($end-$start)+1;
    $pr_refseq = _rpl_REF("REFERENCE",$altpos,$prm_s,$prm_e+$targetLen,$refseq,$list_cp);
    $pr_refseq = str_replace("-", "", $pr_refseq);
    $res = _genPrimer3Query($start,$end,$targetLen,$pr_refseq,$prm_s,$prm_width,$altpos,$prm_chr,$prm_avd,$prm_type,$prm_Ns);
    $resArray = explode("@",$res);
    echo $resArray[0];
    exit;
}else{
    set_time_limit(0);
    $range=explode("-",$prm_tgt);
    $start=0;
    $end=0;
    if($prm_var=="DEL"){
        $start=$range[0]-1;
        $end=$range[1]-1;
    }else{
        $start=$range[0];
        $end=$range[1];
    }
    $targetLen=($end-$start)+1;
    $name=$prm_chr."_".(int)$range[0]."-".(int)$range[1];
    $pr_refseq = _rpl_REF("REFERENCE",$altpos,$prm_s,$prm_e+$targetLen,$refseq,$list_cp);
    $pr_refseq = str_replace("-", "", $pr_refseq);
    $res = _genPrimer3Query($start,$end,$targetLen,$pr_refseq,$prm_s,$prm_width,$altpos,$prm_chr,$prm_avd,$prm_type,$prm_Ns);
    $query = _prepareQuery($name,$res,$prm_p3prm,$primer3ThermPath_checked);
    $p3Res = _execPrimer3($query,$primer3Path_checked);
    $primerRes = _genResult($name,$res,$prm_p3prm,$p3Res);
    echo $primerRes;
    exit;
}

$t=count($seqname);
for($i=0; $i<$t; $i++){
    $sn = array_shift($seqname);
    echo ">".$sn."\n";
    $altseq = strtoupper($refseq);
    $ac = array_shift($list);
    $empty_sites = _EMPDP($ac,$prm_chr,$prm_s,$prm_e,$conn);
    $altseq = _rpl_N($empty_sites,$prm_s,$altseq);
    $altseq = _rpl_VAR($ac,$altpos,$prm_s,$prm_e,$altseq,$list_cp,$prm_qual,$prm_dp);
    if ($prm_width != 0 ){ 
        $altseq = wordwrap($altseq, $prm_width, "\n", true);
    }
    echo $altseq."\n";
}
oci_close($conn);


//-----------------------------------------functions------------------------------------------------------------//
///////////// template seq
function _rpl_REF($a,$b,$c,$d,$e,$f){
    $rtnseq = $e;
    $list = $a;
    $strbuf=array();
    $x=count($f);
    $f_chk=$f;
    $lenmax=array();

    for($i=0;$i<$x;$i++){
        $each_acces = array_shift($f_chk);
        for($z=$c; $z<=$d; $z++){
            if(array_key_exists($each_acces.":".$z, $b)){
                $ins_inf = explode(":",$b[$each_acces.":".$z]);
                if($ins_inf[0] == "i"){
                    $reflen = strlen($ins_inf[1]);
                    $altlen = strlen($ins_inf[2]);
                    $len_i = $altlen - $reflen;
                    $replace_pos = $z + 1 - $c;
                    if(array_key_exists($replace_pos, $lenmax)){
                        if($len_i > $lenmax[$replace_pos]){
                            $lenmax[$replace_pos]=$len_i;
                        }
                    }else{
                        $lenmax[$replace_pos]=$len_i;
                    }
                } 
            }
        }
    }
    for($i=0;$i<$x;$i++){
        $each_acces = array_shift($f);
        for($z=$c; $z<=$d; $z++){
            if(array_key_exists($each_acces.":".$z, $b)){
                $ins_inf2 = explode(":",$b[$each_acces.":".$z]);
                if($ins_inf2[0] == "i" and $list != $each_acces ){
                    $reflen = strlen($ins_inf2[1]);
                    $altlen = strlen($ins_inf2[2]);
                    $len_i = $altlen - $reflen;
                    $replace_pos = $z + 1 - $c;
                    $gap="";
                    if($lenmax[$replace_pos] > $len_i){
                        $len_i=$len_i+($lenmax[$replace_pos]-$len_i);
                    }
                    for($i=0; $i<$len_i; $i++){
                        $gap=$gap."-";
                    }
                    $strbuf[$replace_pos]=$gap.":".$len_i.":".$replace_pos;
                } else if($ins_inf2[0] == "i" and $list == $each_acces ){
                    //pass
                }
            }
        }
    }
    $pointer=0;
    ksort($strbuf);
    $ct=count($strbuf);
    for($i=0; $i<$ct; $i++){
        $str = array_shift($strbuf);
        $str_array = explode(":",$str);
        $replace_pos = $str_array[2] + $pointer;
        $rtnseq = substr_replace($rtnseq, $str_array[0], $replace_pos ,0);
        $pointer +=$str_array[1];
    }
    return $rtnseq;
}

///////////// INS _rpl_INS($list,$b,$c,$d,$rtnseq,$f,$ql,$dp);
function _rpl_INS($a,$b,$c,$d,$e,$f,$ql,$dp){
    $rtnseq = $e;
    $list = $a;
    $strbuf=array();
    $ins_check=array();
    $x=count($f);
    $f_chk=$f;
    $lenmax=array();
    
    for($i=0;$i<$x;$i++){
        $each_acces = array_shift($f_chk);
        for($z=$c; $z<=$d; $z++){
            if(array_key_exists($each_acces.":".$z, $b)){
                $ins_inf = explode(":",$b[$each_acces.":".$z]);
                if($ins_inf[0] == "i"){
                    $reflen = strlen($ins_inf[1]);
                    $altlen = strlen($ins_inf[2]);
                    $len_i = $altlen - $reflen;
                    $replace_pos = $z + 1 - $c;
                    if(array_key_exists($replace_pos, $lenmax)){
                        if($len_i > $lenmax[$replace_pos]){
                            $lenmax[$replace_pos]=$len_i;
                        }
                    }else{
                        $lenmax[$replace_pos]=$len_i;
                    }
                } 
            }
        }
    }
    for($i=0;$i<$x;$i++){
        $each_acces = array_shift($f);
        for($z=$c; $z<=$d; $z++){
            if(array_key_exists($each_acces.":".$z, $b)){
                $ins_inf = explode(":",$b[$each_acces.":".$z]);
                if($ins_inf[0] == "i" and $list != $each_acces and ! array_key_exists($z, $ins_check)){
                    $reflen = strlen($ins_inf[1]);
                    $altlen = strlen($ins_inf[2]);
                    $len_i = $altlen - $reflen;
                    $replace_pos = $z + 1 - $c;
                    $gap="";
                    if($lenmax[$replace_pos] > $len_i){
                        $len_i=$len_i+($lenmax[$replace_pos]-$len_i);
                    }
                    for($l=0; $l<$len_i; $l++){
                        $gap=$gap."-";
                    }
                    $strbuf[$replace_pos]=$gap.":".$len_i.":".$replace_pos;
                } else if($ins_inf[0] == "i" and $list == $each_acces ){
                    $ins_check[$z]=1;
                    $reflen = strlen($ins_inf[1]);
                    $altlen = strlen($ins_inf[2]);
                    $len_i = $altlen - $reflen;
                    $replace_pos = $z + 1 - $c;
                    
                    if($ql <= $ins_inf[3] and $dp <= $ins_inf[4]){
                        $gap="";
                        if($lenmax[$replace_pos] > $len_i){
                            for($m=0; $m<$lenmax[$replace_pos]-$len_i; $m++){
                                $gap=$gap."-";
                            }
                            $len_org=$len_i;
                            $len_i=$len_i+($lenmax[$replace_pos]-$len_i);
                            $strbuf[$replace_pos]=substr($ins_inf[2], 1, $len_org).$gap.":".$len_i.":".$replace_pos;
                        }else{
                            $strbuf[$replace_pos]=substr($ins_inf[2], 1, $len_i).":".$len_i.":".$replace_pos;
                        }
                    }else{
                        $gap="";
                        if($lenmax[$replace_pos] > $len_i){
                            $len_i=$len_i+($lenmax[$replace_pos]-$len_i);
                        }
                        for($n=0; $n<$len_i; $n++){
                            $gap=$gap."N";
                        }
                        $strbuf[$replace_pos]=$gap.":".$len_i.":".$replace_pos;
                    }
                }
            }
        }
    }
    $pointer=0;
    ksort($strbuf);
    $ct=count($strbuf);
    for($o=0; $o<$ct; $o++){
        $str = array_shift($strbuf);
        $str_array = explode(":",$str);
        $replace_pos = $str_array[2] + $pointer;
        $rtnseq = substr_replace($rtnseq, $str_array[0], $replace_pos ,0);
        $pointer +=$str_array[1];
    }
    return $rtnseq;
}

///////////// SNP  _rpl_VAR($ac,$altpos,$prm_s,$prm_e,$altseq,$list_cp,$prm_qual,$prm_dp);
function _rpl_VAR($a,$b,$c,$d,$e,$f,$ql,$dp){
    $rtnseq = $e;
    $list = $a;
    $pointer=0;
    $strbuf=array();
    for($y=$c; $y<=$d; $y++){
        if(array_key_exists($list.":".$y, $b)){
            $var_inf = explode(":",$b[$list.":".$y]);
            if($var_inf[0] == "s"){
                if($ql <= $var_inf[3] and $dp <= $var_inf[4]){
                    $replace_pos = $y - $c + $pointer;
                    $rtnseq = substr_replace($rtnseq, $var_inf[2], $replace_pos, 1 );
                }else{
                    $replace_pos = $y - $c + $pointer;
                    $rtnseq = substr_replace($rtnseq, "N", $replace_pos, 1 );
                }
            } else if ($var_inf[0] == "i"){
                $reflen = strlen($var_inf[1]);
                $altlen = strlen($var_inf[2]);
                $len_i = $altlen - $reflen;
                $replace_pos = $y + 1 - $c + $pointer;
                if($ql <= $var_inf[3] and $dp <= $var_inf[4]){
                    $strbuf[$replace_pos]=substr($var_inf[2], 1, $len_i).":".$len_i.":".$replace_pos;
                }else{
                    $gap="";
                    for($i=0; $i<$len_i; $i++){
                        $gap=$gap."N";
                    }
                    $strbuf[$replace_pos]=$gap.":".$len_i.":".$replace_pos;
                }
            } else if ($var_inf[0] == "d"){
                $reflen = strlen($var_inf[1]);
                $altlen = strlen($var_inf[2]);
                $len_d = $reflen - $altlen;
                $replace_pos = $y - $c + $pointer;
                if($ql <= $var_inf[3] and $dp <= $var_inf[4]){
                    for($i=0; $i<$len_d; $i++){
                        $rtnseq = substr_replace($rtnseq, "-", $replace_pos, 1 );
                        $replace_pos++;
                    }
                }else{
                    for($i=0; $i<$len_d; $i++){
                        $rtnseq = substr_replace($rtnseq, "N", $replace_pos, 1 );
                        $replace_pos++;
                    }
                }
            }
        }
    }
    $pr_rtnseq = _rpl_INS($list,$b,$c,$d,$rtnseq,$f,$ql,$dp);
    return $pr_rtnseq;
}

/////////////"N" postion _rpl_N($empty_sites,$prm_s,$altseq);
function _rpl_N($a,$b,$c){
    $rtnseq = $c;
    $x=count($a);
    for($i=0;$i<$x;$i++){
        $Npos=array_shift($a);
        $replace_pos = $Npos - $b;
        $rtnseq = substr_replace($rtnseq, "N", $replace_pos, 1 );
    }
    return $rtnseq;
}

/////////////variants  _VAR($list,$prm_chr,$prm_s,$prm_e);
function _VAR($list,$b,$c,$d,$conn,$mode,$seqname,$dp,$qual){
    /*
    This function gets ARRAY has variant position about each accession.
    */
    $var_array = array();
    $x=count($list);
    if($mode == "a"){
        $dp=0;
        $qual=0;
    }
    for($i=0;$i<$x;$i++){
        $p=array_shift($list);
        $query = "SELECT pos,variant,ref,alt,qual,dp FROM ".$p."_variant WHERE chr=:bd_chr and pos >=:bd_start and pos <=:bd_end and dp >=:bd_dp and qual >=:bd_qual ";
        $stmt = oci_parse($conn, $query);
        oci_bind_by_name($stmt, ':bd_chr', $b, -1, SQLT_CHR);
        oci_bind_by_name($stmt, ':bd_start', $c, -1, SQLT_INT);
        oci_bind_by_name($stmt, ':bd_end', $d, -1, SQLT_INT);
        oci_bind_by_name($stmt, ':bd_dp', $dp, -1, SQLT_INT);
        oci_bind_by_name($stmt, ':bd_qual', $qual, -1, SQLT_INT);
        oci_set_prefetch($stmt, 500); 
        oci_execute($stmt);
        while (($row = oci_fetch_array($stmt, OCI_NUM + OCI_RETURN_NULLS))!= false) {
            $alts = explode(",", $row[3]);
            if($mode == "a"){
                $var_array[$p.":".$row[0]]=$row[1].":".strtoupper($row[2]).":".strtoupper($alts[0]).":".$row[4].":".$row[5];
            }else{
                if(array_key_exists($row[0], $var_array)){
                    $var_array[$row[0]]=$var_array[$row[0]].",".$seqname[$p];
                }else{
                    $var_array[$row[0]]=$row[0]."\t".strtoupper($row[2])."/".strtoupper($alts[0])."\t".$row[1]."\t".$seqname[$p];
                }
            }
        }
        oci_free_statement($stmt);
    }
    return $var_array;
}

/////////////ummapped postion  _EMPDP($ac,$prm_chr,$prm_s,$prm_e);
function _EMPDP($a, $b, $c, $d,$conn){
    $null=array();
    $param=$b."_b";
    $query="SELECT pos FROM ".$a."_accession WHERE ".$param." is null and pos >=:bd_start and pos <=:bd_end ";
    $stmt = oci_parse($conn, $query);
    oci_bind_by_name($stmt, ':bd_start', $c, -1, SQLT_INT);
    oci_bind_by_name($stmt, ':bd_end', $d, -1, SQLT_INT);
    oci_set_prefetch($stmt, 1000); 
    oci_execute($stmt);
    while (($row = oci_fetch_array($stmt, OCI_NUM + OCI_RETURN_NULLS))!= false) {
        $null[]=$row[0];
    }
    oci_free_statement($stmt);
    return $null;
}

///Getting template sequences using Redis (prm_chr, prm_s, prm_e, connRedis)
function _getRefseqRedis($a,$b,$c,$redis){
    $refseq = "";
    $key = "";
    $field = 0;
    for($x=$b; $x<$c+1; $x++){
        $key = $a.":".(int)($x/100);
        $field = $x%100;
        if($redis->exists($key)){
            $refseq .= $redis->hGet($key,$field);
        }
    }
    return $refseq;
}

/////////////ref-seq _GETREFSEQ($prm_chr, $prm_s, $prm_e);
function _GETREFSEQ($a,$b,$c,$conn){
    $refseq="";
    $query = "SELECT ".$a."_f FROM sys_fasta WHERE pos >=:bd_start and pos <=:bd_end";
    $stmt = oci_parse($conn, $query);
    oci_bind_by_name($stmt, ':bd_start', $b, -1, SQLT_INT);
    oci_bind_by_name($stmt, ':bd_end', $c, -1, SQLT_INT);
    oci_set_prefetch($stmt, 1000); 
    oci_execute($stmt);
    while (($row = oci_fetch_array($stmt, OCI_NUM + OCI_RETURN_NULLS))!= false) {
        $refseq = $refseq.$row[0];
    }
    oci_free_statement($stmt);
    return $refseq;
}

/////////////seq_name _rpl_REF("REFERENCE",$altpos,$prm_s,$prm_e,$refseq,$list_cp)
function _HEADERFA($a,$b,$c,$d,$e,$conn,$mode){
    $str = array();
    $d = _validate_name($d);
    $e = _validate_group($e);
    $query = "SELECT ".$d.", ".$e.",accession_db FROM sys_accession WHERE accession_db=:bd_param ";
    $stmt = oci_parse($conn, $query);
    for($i=0;$i<count($a);$i++){
        oci_bind_by_name($stmt, ':bd_param', $a[$i], -1, SQLT_CHR);
        oci_execute($stmt);
        while (($row = oci_fetch_array($stmt, OCI_NUM + OCI_RETURN_NULLS))!= false) {
            if($mode == "a"){
                if (!isset($_SERVER["HTTP_HOST"])) {
                    $str[$i] = $row[2];
                }else{
                    $str[$i] = $row[0]."_".$row[1];
                }
            }else{
                $str[$a[$i]]=$row[0];
            }
        }
    }
    oci_free_statement($stmt);
    return $str;
}

function _genPrimer3Query($range0,$range1,$targetLen,$pr_refseq,$prm_s,$prm_width,$altpos,$prm_chr,$prm_avd,$prm_type,$prm_Ns){
    /* 
    This function generates template sequence for primer3web or query for primer3 on your server.
    --template sequence ($prm_type==b)=> the function generates HTML included the sequence for primer3Web.
    --run primer3 on the server ($prm_type==c)=> the function generates template sequence for primer3 and target position. $res = SEQ|target|targetLength|$prm_avd
    */
    $pointer=0;
    $numarray = count($altpos);
    
    if($prm_Ns){
        if($numarray > 1){
            $seqarray = str_split($pr_refseq,1);
            $numNs=0;
            for ($i=0; $i<$numarray; $i++){
            $key = key($altpos);
            $varOnFlk=explode("\t", $altpos[$key]);
            if($key != $range0){
                $varOnFlk=explode("\t", $altpos[$key]);
                if($varOnFlk[2]=="d"){
                    $targetSeq=explode("/", $varOnFlk[1]);
                    $numNs = abs(strlen($targetSeq[0])-strlen($targetSeq[1]));
                    for($a=0; $a<$numNs; $a++){
                        $seqarray[$key-$prm_s+$a]="N";
                    }
                }elseif($varOnFlk[2]=="i"){
                    $rplNs="";
                    $targetSeq=explode("/", $varOnFlk[1]);
                    $numNs = abs(strlen($targetSeq[1])-strlen($targetSeq[0]));
                    if($key < $range0){
                        $pointer = $pointer+($numNs);
                    }
                    $seqarray[$key-$prm_s]=$seqarray[$key-$prm_s].str_repeat("N", $numNs);
                }else{
                    $seqarray[$key-$prm_s]="N";
                }
            }
            next($altpos);
            }
            reset($altpos);
            $pr_refseq = implode("",$seqarray);
        }
    }
    $fivePrm = substr($pr_refseq, 0, ($range0-$prm_s+$pointer));
    $tgt = substr($pr_refseq, ($range0-$prm_s+$pointer), $targetLen);
    $threePrm = substr($pr_refseq, ($range0-$prm_s+$targetLen+$pointer));
    $header="<div style=\"margin-left:75px;\">TARGET: ".$prm_chr.":".$range0."-".$range1."</div>";
    $tablehead="<table class=\"fontCourierNew\" width=\"585px\" cellspacing=\"0\" border=\"1\" style=\"margin-left:60px;\" ><tr><td width=\"82%\">";
    $tabletail="</td></tr></table>";
    
    if($prm_avd){
        $fivePrmLeft = substr($fivePrm, 0, strlen($fivePrm)-$prm_avd);
        $fivePrmRight = substr($fivePrm, strlen($fivePrm)-$prm_avd);
        $threePrmLeft = substr($threePrm,  0, $prm_avd);
        $threePrmRight = substr($threePrm, $prm_avd);
        if($prm_type=="c"){// for runPrimer3()
            $res = $fivePrmLeft.$fivePrmRight.$tgt.$threePrmLeft.$threePrmRight;
            $res = $res."|".($range0-$prm_s+1+$pointer)."|".$targetLen."|".$prm_avd;
            return $res;
        }
        $res = $fivePrmLeft.";".$fivePrmRight.":[".$tgt."];".$threePrmLeft.":".$threePrmRight;
        $res = wordwrap($res, $prm_width, "<br>", true);
        $res = preg_replace("/\];/", "]</font>;", $res);
        $res = preg_replace("/:\[/", ":<font color='#ff0000'>[", $res);
        $res = preg_replace("/;/", "<font color='#0000ff'>;", $res);
        $res = preg_replace("/:/", ":</font>", $res);
        $res = preg_replace("/;/", "&lt;", $res);
        $res = preg_replace("/:/", "&gt;", $res);
        $res = preg_replace("/N/", "<font color='#ffa500'>N</font>", $res);
        $res=$header.$tablehead.$res.$tabletail."<br>";
    }else{
        $res = $fivePrm."[".$tgt."]".$threePrm;
        if($prm_type=="c"){// for runPrimer3()
            $res = $fivePrm.$tgt.$threePrm;
            $res = $res."|".($range0-$prm_s+1+$pointer)."|".$targetLen."|".$prm_avd;
            return $res;
        } 
        $res = wordwrap($res, $prm_width, "<br>", true);
        $res = preg_replace("/\]/", "]</font>", $res);
        $res = preg_replace("/\[/", "<font color='#ff0000'>[", $res);
        $res = preg_replace("/;/", "&lt;", $res);
        $res = preg_replace("/:/", "&gt;", $res);
        $res = preg_replace("/N/", "<font color='#ffa500'>N</font>", $res);
        $res = $header.$tablehead.$res.$tabletail."<br>";
    }
    $res=$res."<div style=\"margin-left:75px;\">Primer3Web: <a href=\"http://primer3.ut.ee/\" target=\"_blank\">http://primer3.ut.ee/</a><br><br>";
    if($numarray > 1){
        $res = $res."<font color=\"#ffa500\">Caution!</font> Flanking region has ".($numarray-1)." variant(s).<br>";
        if($numarray > 10){
            $res=$res."Only 10 variants are displayed.<br></div>";
            $numarray = 10;
        }else{
            $res=$res."</div>";
        }
        $res=$res."<table class=\"fontCourierNew\" width=\"585px\" cellspacing=\"0\" border=\"1\" style=\"margin-left:60px;\" >
        <tr bgcolor=\"#CCCCCC\"><td width=\"55%\">Accession</td><td width=\"15%\">Position</td><td width=\"30%\">REE/ALT</td>";
        for ($i=0; $i<$numarray; $i++){
            $key = key($altpos);
            $varOnFlk=explode("\t", $altpos[$key]);
            if($varOnFlk[2]=="d"){
                $key--;
            }
            if($key != $range0){
                $res=$res."<tr><td>".wordwrap($varOnFlk[3],"40","<br>",true)."</td><td>".$varOnFlk[0]."</td><td>".wordwrap($varOnFlk[1],"20","<br>",true)."</td></tr>";
            }
            next($altpos);
        }
        $res=$res."</table><br><br>";
    }
    return $res;
}

function _prepareQuery($name,$res,$prm_p3prm,$primer3ThermPath){
    $param = explode(",", $prm_p3prm);
    $resArray = explode("|", $res);
    $targetStart=$resArray[1]-1;
    $exStart=$targetStart-$resArray[3];
    $exEnd=$targetStart+$resArray[2];
    // create primer3 query file.
$query = <<< EOT
SEQUENCE_ID={$name}
SEQUENCE_TEMPLATE={$resArray[0]}
SEQUENCE_TARGET={$targetStart},{$resArray[2]}
SEQUENCE_EXCLUDED_REGION={$exStart},{$resArray[3]} {$exEnd},{$resArray[3]}
PRIMER_TASK=pick_detection_primers
PRIMER_PICK_LEFT_PRIMER=1
PRIMER_PICK_INTERNAL_OLIGO=0
PRIMER_PICK_RIGHT_PRIMER=1
PRIMER_OPT_SIZE={$param[2]}
PRIMER_MAX_SIZE={$param[3]}
PRIMER_MIN_SIZE={$param[4]}
PRIMER_OPT_TM={$param[5]}
PRIMER_MAX_TM={$param[6]}
PRIMER_MIN_TM={$param[7]}
PRIMER_MAX_DIFF_TM={$param[8]}
PRIMER_MAX_NS_ACCEPTED=1
PRIMER_PRODUCT_SIZE_RANGE={$param[0]}-{$param[1]}
PRIMER_THERMODYNAMIC_PARAMETERS_PATH={$primer3ThermPath}
PRIMER_EXPLAIN_FLAG=1
PRIMER_MAX_NS_ACCEPTED=0
PRIMER_LOWERCASE_MASKING={$param[9]}
=
EOT;
    return $query;
}

function _execPrimer3($query,$primer3Path){
    if (!file_exists($primer3Path) || preg_match("/^\S*primer3_core$/", $primer3Path) != 1) {
        echo "Error: Primer3 was not found.";
        exit;
    } 
    $fp = tmpfile();
    fwrite($fp, $query);
    rewind($fp);
    $tmparray = stream_get_meta_data($fp);
    $resArray=Array();
    exec(sprintf("%s %s < %s", $primer3Path, "-format_output", $tmparray["uri"]), $resArray, $return);
    $primer = implode("\n", $resArray);
    fclose($fp);
    if($return == 1){
        echo "Error: Can not execute Primer3.";
        exit;
    }
    return $primer;
} 

function _genResult($name,$res,$prm_p3prm,$p3Res){
    $param = explode(",", $prm_p3prm);
    $resArray = explode("|", $res);
    $targetStart=$resArray[1]-1;
    $exStart=$targetStart-$resArray[3];
    $exEnd=$targetStart+$resArray[2];
    $pointer=0;
    $printseq="";
    $printseq = wordwrap($resArray[0], 80, "<br>", true);
    
    if($resArray[3] != 0){
        $printseq = substr_replace($printseq,"<font color='#0000ff'>",$exStart+$pointer+(((int)($exStart/80))*4),0);
        $pointer = $pointer+22;
        $printseq = substr_replace($printseq,"</font>",$exStart+$resArray[3]+$pointer+(((int)(($exStart+$resArray[3])/80))*4),0);
        $pointer = $pointer+7;
    }
    $printseq = substr_replace($printseq,"<font color='#ff0000'>",$targetStart+$pointer+(((int)($targetStart/80))*4),0);
    $pointer = $pointer+22;
    $printseq = substr_replace($printseq,"</font>",$targetStart+$resArray[2]+$pointer+(((int)(($targetStart+$resArray[2])/80))*4),0);
    $pointer = $pointer+7;
    if($resArray[3] != 0){
        $printseq = substr_replace($printseq,"<font color='#0000ff'>",$exEnd+$pointer+(((int)($exEnd/80))*4),0);
        $pointer = $pointer+22;
        $printseq = substr_replace($printseq,"</font>",$exEnd+$resArray[3]+$pointer+(((int)(($exEnd+$resArray[3])/80))*4),0);
        $pointer = $pointer+7;
    }
    $printseq = preg_replace("/N/", "<font color='#ffa500'>N</font>", $printseq);
    $leftArray = Array();
    $rightArray = Array();
    $p3resArray = Array();
    $p3resArray = explode("\n", $p3Res);

    $pattern_done = "/NO PRIMERS FOUND/";
    $pattern_prmL = "/.*LEFT PRIMER\s+(\d+)\s+(\d+).*\s+(\w+)$/";
    $pattern_prmR = "/.*RIGHT PRIMER\s+(\d+)\s+(\d+).*\s+(\w+)$/";
    $t=count($p3resArray);
    for($i=0; $i<$t; $i++){
        if(preg_match($pattern_done, $p3resArray[$i], $match_done) != 0){
            $i=$t-1;
        }
        if(preg_match($pattern_prmL, $p3resArray[$i], $match_done) != 0){
            $leftArray[$i]=$match_done[1].":".$match_done[2].":".$match_done[3];
        }
        if(preg_match($pattern_prmR, $p3resArray[$i], $match_done) != 0){
            $rightArray[$i]=$match_done[1].":".$match_done[2].":".$match_done[3];
        }
    }
    $lprmPos = implode("-", $leftArray);
    $rprmPos = implode("-", $rightArray);
    $primer=$p3Res."---SPLIT---".$printseq."--split--".$lprmPos."--split--".$rprmPos;
    return $primer;
}

///Functions///
function _validate_chrs($conn, $prm_Chr){
    $flag = false;
    $query = "select seq from sys_chromosome where id=:bd_chr and ROWNUM < 2 ";
    $stmt = oci_parse($conn, $query);
    oci_bind_by_name($stmt, ':bd_chr', $prm_Chr, -1, SQLT_CHR);
    oci_execute($stmt);
    while (($row = oci_fetch_array($stmt, OCI_BOTH + OCI_RETURN_NULLS))!= false) {
        $flag = true ;
    }
    oci_free_statement($stmt);
    if($flag){
       return true;
    }else{
       return false;
    }
}

function _validate_each_acc($list){
    $num = count($list);
    for($a=0;$a<$num;$a++){
        if (preg_match("/^d\d+$/i", $list[$a])) {
            //pass
        }else{
           return false;
        }
    }
    return true;
}

function _validate_name($str){
    if($str == "id"){
        $str="accession_id";
    }else if($str == "name"){
        $str="accession_name";
    }else{
        return false;
    }
    return $str;
}

function _validate_group($str){
    $keys = array(
        "variaty" => "1",
        "sub_variety" => "1",
        "origin" => "1",
        "origin_2" => "1",
        "type" => "1",
    );
    if($str == "subvariety" ){$str = "sub_variety";}
    if(array_key_exists($str, $keys)){
        return $str;
    }else{
        return false;
    }
}

function _valRefName($prm_ref,$reference){
    $ret=0;
    if($prm_ref==$reference){$ret=1;}
    return $ret;
}

function _validate_num($num){
    if (preg_match("/^\d+$/i", $num)) {
       return true;
    }else{
       return false;
    }
}

function returnError($str){
    echo $str;
}

function _stopError($str){
    echo $str;
    exit;
}
?>