/* 
  This program is free software. It comes without any warranty, to
  the extent permitted by applicable law. You can redistribute it
  and/or modify it under the terms of the Do What The Fuck You Want
  To Public License, Version 2, as published by Sam Hocevar. See
  http://sam.zoy.org/wtfpl/COPYING for more details.
*/

window.onload=function() {
  //dbg=document.createElement("div")
  //document.body.appendChild(dbg)
  field_width=48
  field_height=30
  dot_width=10
  dot_height=10
  create_field()
  adjust_field()
  
  point=new Array()
  bpoints=new Array()
  points=new Array()
  lines=new Array()
  
  speed=5
  gameload()
}

function create_field() {
  bfield=document.createElement("div")
  bfield.id="bfield"
  field=document.createElement("div")
  field.id="field"
  document.body.appendChild(bfield)
  document.body.appendChild(field)
  
  dotdiv=document.createElement("div")
  dotdiv.id="dot"
  field.appendChild(dotdiv)
  
  score_div=document.createElement("div")
  score_div.style.cssFloat="left"
  score_val=document.createTextNode("Score: 0")
  score_div.appendChild(score_val)
  
  speed_div=document.createElement("div")
  speed_div.style.cssFloat="right"
  speed_val=document.createTextNode("Speed: 5")
  speed_div.appendChild(speed_val)
  
  bfield.appendChild(score_div)
  bfield.appendChild(speed_div)
}

function adjust_field() {
  bfield.style.width=field_width*dot_width-6+"px"
  bfield.style.height="24px"
  bfield.style.marginLeft=-(field_width*dot_width/2)-2+"px"
  bfield.style.marginTop=-(field_height*dot_height/2)-18+"px"
  
  field.style.width=field_width*dot_width+"px"
  field.style.height=field_height*dot_height+"px"
  field.style.marginLeft=-(field_width*dot_width/2)-2+"px"
  field.style.marginTop=-(field_height*dot_height/2)+14+"px"
}

function gameload() {
  score=0
  score_val.data="Score: 0"
  
  var i
  var lines_len=lines.length
  
  for (i=0;i<lines_len;i++) {
    field.removeChild(lines[i])
  }
    
  point.splice(0,point.length)
  bpoints.splice(0,bpoints.length)
  lines.splice(0,lines_len)
  
  point[0]=[2,3]
  point[1]=[4,3]
  
  dir=2
  
  dotx=-1
  doty=-1
  
  mov=false
  gameover=false
  movement()
  placedot()
}

document.onkeydown=function(e) {
  var key
  if (window.event) key=window.event.keyCode
  else if (e) key=e.which
  else key=0
  if (key==19 && mov && !gameover) mov=false
  else if (key==19 && !mov && !gameover) mov=true
  
  if (key>=37 && key<=40) {
    diff=[point[point.length-2][0]-point[point.length-1][0],point[point.length-2][1]-point[point.length-1][1]]
    if (diff[0]<0) diff[0]=-diff[0]
    if (diff[1]<0) diff[1]=-diff[1]
    if (diff[0]>1 || diff[1]>1) {
      var coor_a, coor_b
      
      if (key==38 && dir!=1 && dir!=3) {
        coor_a=[0,-1]
        if (dir==2) coor_b=[-1,0]
        else if (dir==4) coor_b=[1,0]
        dir=1
      }
      else if (key==39 && dir!=2 && dir!=4) {
        coor_a=[1,0]
        if (dir==1) coor_b=[0,1]
        else if (dir==3) coor_b=[0,-1]
        dir=2
      }
      else if (key==40 && dir!=3 && dir!=1) {
        coor_a=[0,1]
        if (dir==2) coor_b=[-1,0]
        else if (dir==4) coor_b=[1,0]
        dir=3
      }
      else if (key==37 && dir!=4 && dir!=2) {
        coor_a=[-1,0]
        if (dir==3) coor_b=[0,-1]
        else if (dir==1) coor_b=[0,1]
        dir=4
      }

      if (coor_a) {
        point[point.length-1]=[point[point.length-1][0]+coor_b[0],point[point.length-1][1]+coor_b[1]]
        point[point.length]=[point[point.length-1][0]+coor_a[0],point[point.length-1][1]+coor_a[1]]
      }
    }
  }
  if (((key>=37 && key<=40) || key==32 || key==13) && !mov && !gameover) {
    mov=true
    movement()
  }
  if ((key==32 || key==13) && !mov && gameover) {
    gameload()
  }
  if (key==33 && speed<9) change_speed(1)
  else if (key==34 && speed>1) change_speed(-1)
}

function change_score(ud) {
  score+=ud
  score_val.data="Score: "+score
}

function change_speed(ud) {
  speed+=ud
  speed_val.data="Speed: "+speed
}

function placedot() {
  var x, y, coor, t_ok
  var point_len=point.length
  var bpoints_len=bpoints.length
  var place_ok=false
  var full_len=point_len+bpoints_len
  //var a=0
  //dbg.innerHTML=a+":<br />"
  do {
    x=Math.floor(Math.random()*field_width)
    y=Math.floor(Math.random()*field_height)
    t_ok = true
    for (i=1;i<full_len;i++) {
      if (i<point_len) coor=[[point[i-1][0],point[i-1][1]],[point[i][0],point[i][1]]]
      else coor=bpoints[i-point_len]
      
      if (coor[0][1]>coor[1][1] || coor[0][0]>coor[1][0]) coor=[coor[1],coor[0]]
      
      coor[0][1]=coor[0][1]%(field_height)
      coor[1][1]=coor[1][1]%(field_height)
      if (coor[0][1]<0) coor[0][1]+=field_height
      if (coor[1][1]<0) coor[1][1]+=field_height
      if (coor[1][1]<coor[0][1]) coor[1][1]=field_height-1
      
      coor[0][0]=coor[0][0]%(field_width)
      coor[1][0]=coor[1][0]%(field_width)
      if (coor[0][0]<0) coor[0][0]+=field_width
      if (coor[1][0]<0) coor[1][0]+=field_width
      if (coor[1][0]<coor[0][0]) coor[1][0]=field_width-1
          
      if (i>=point_len && coor[0][0]<coor[1][0]) coor[1][0]--
      if (i>=point_len && coor[0][1]<coor[1][1]) coor[1][1]--
      
      if (x>=coor[0][0] && x<=coor[1][0] && y>=coor[0][1] && y<=coor[1][1]) {
        t_ok=false
      }
      //dbg.innerHTML+=x+","+y+" | "+coor[0]+"-"+coor[1]+"<br />"
    }
  if (t_ok)
    place_ok=true
  //a++
  } while (!place_ok)
  
  dotx=x
  doty=y  
  
  dotdiv.style.width=dot_width+"px"
  dotdiv.style.height=dot_height+"px"
  dotdiv.style.left=dotx*dot_width+"px"
  dotdiv.style.top=doty*dot_height+"px"
}

function movement() {
  bpoints.splice(0,bpoints.length)
  points.splice(0,points.length)
  var point_len=point.length
  var i
    
  var coorl, iffao
  if (dir==1) coorl=[0,1]
  else if (dir==2) coorl=[-1,0]
  else if (dir==3) coorl=[0,-1]
  else if (dir==4) coorl=[1,0]
  
  var line_height, line_width, x, y
  for (i=0;i<point_len-1;i++) {
    if (point[i][0]==point[i+1][0] && point[i][1]>point[i+1][1]) {
      line_height=point[i][1]-point[i+1][1]+1
      line_width=1
      x=point[i][0]
      y=point[i+1][1]
    }
    else if (point[i][1]==point[i+1][1] && point[i+1][0]>point[i][0]) {
      line_height=1
      line_width=point[i+1][0]-point[i][0]+1
      x=point[i][0]
      y=point[i][1]
    }
    else if (point[i][0]==point[i+1][0] && point[i][1]<point[i+1][1]) {
      line_height=point[i+1][1]-point[i][1]+1
      line_width=1
      x=point[i][0]
      y=point[i][1]
    }
    else if (point[i][1]==point[i+1][1] && point[i+1][0]<point[i][0]) {
      line_height=1
      line_width=point[i][0]-point[i+1][0]+1
      x=point[i+1][0]
      y=point[i][1]
    }
    
    if (x>field_width-1) x=x%(field_width)
    else if (x<0) x=field_width+x%(field_width)
    if (y>field_height-1) y=y%(field_height)
    else if (y<0) y=field_height+y%(field_height)
    
    if (x==field_width) x=0
    if (y==field_height) y=0
            
    if (x+line_width>field_width) {
      bpoints[bpoints.length]=[[0,y],[(x+line_width)%(field_width),y]]
      line_width=field_width-x
    }
    if (y+line_height>field_height) {
      bpoints[bpoints.length]=[[x,0],[x,(y+line_height)%(field_height)]]
      line_height=field_height-y
    }
    
    line_height*=dot_height
    line_width*=dot_width
    x*=dot_width
    y*=dot_height
        
    points[points.length]=[line_height,line_width,x,y]
  }
  
  var bpoints_len=bpoints.length
  
  for (i=0;i<bpoints_len;i++) {
    if (bpoints[i][0][0]==bpoints[i][1][0] && bpoints[i][0][1]>bpoints[i][1][1]) {
      line_height=bpoints[i][0][1]-bpoints[i][1][1]
      line_width=1
      x=bpoints[i][0][0]
      y=bpoints[i][1][1]
    }
    else if (bpoints[i][0][1]==bpoints[i][1][1] && bpoints[i][1][0]>bpoints[i][0][0]) {
      line_height=1
      line_width=bpoints[i][1][0]-bpoints[i][0][0]
      x=bpoints[i][0][0]
      y=bpoints[i][0][1]
    }
    else if (bpoints[i][0][0]==bpoints[i][1][0] && bpoints[i][0][1]<bpoints[i][1][1]) {
      line_height=bpoints[i][1][1]-bpoints[i][0][1]
      line_width=1
      x=bpoints[i][0][0]
      y=bpoints[i][0][1]
    }
    else if (bpoints[i][0][1]==bpoints[i][1][1] && bpoints[i][1][0]<bpoints[i][0][0]) {
      line_height=1
      line_width=bpoints[i][0][0]-bpoints[i][1][0]
      x=bpoints[i][1][0]
      y=bpoints[i][0][1]
    }
    line_height*=dot_height
    line_width*=dot_width
    x*=dot_width
    y*=dot_height
        
    points[points.length]=[line_height,line_width,x,y]
  }
  
  x=point[point.length-1][0]%field_width
  y=point[point.length-1][1]%field_height
  if (x<0) x+=field_width
  if (y<0) y+=field_height
  
  var cutend=true
  if (x==dotx && y==doty) {
    change_score(speed)
    placedot()
    cutend=false
  }
  
  var full_len=point_len+bpoints_len
  var coor
  
  for (i=1;i<full_len;i++) {
    if (i<point_len) coor=[[point[i-1][0],point[i-1][1]],[point[i][0],point[i][1]]]
    else coor=bpoints[i-point_len]
    
    if (coor[0][1]>coor[1][1] || coor[0][0]>coor[1][0]) coor=[coor[1],coor[0]]
    
    coor[0][1]=coor[0][1]%(field_height)
    coor[1][1]=coor[1][1]%(field_height)
    if (coor[0][1]<0) coor[0][1]+=field_height
    if (coor[1][1]<0) coor[1][1]+=field_height
    if (coor[1][1]<coor[0][1]) coor[1][1]=field_height-1
    
    coor[0][0]=coor[0][0]%(field_width)
    coor[1][0]=coor[1][0]%(field_width)
    if (coor[0][0]<0) coor[0][0]+=field_width
    if (coor[1][0]<0) coor[1][0]+=field_width
    if (coor[1][0]<coor[0][0]) coor[1][0]=field_width-1
    
    var wcoor
    if (dir==2 || dir==3) wcoor=1
    else wcoor=0
    
    if (i==point_len-1 && coor[wcoor][0]==x && coor[wcoor][1]==y) coor[wcoor]=[x+coorl[0],y+coorl[1]]
    else if (i==full_len-1 && coor[wcoor][0]==x+coorl[1]+1 && coor[wcoor][1]==y+coorl[0]+1) coor[wcoor]=[x+coorl[0],y+coorl[1]]
    
    if (i>=point_len && coor[0][0]<coor[1][0]) coor[1][0]--
    if (i>=point_len && coor[0][1]<coor[1][1]) coor[1][1]--
    
    if (x>=coor[0][0] && x<=coor[1][0] && y>=coor[0][1] && y<=coor[1][1]) {
      mov=false
      gameover=true
    }
  }
  
  if (!gameover) {
    var points_len=points.length
    var lines_len=lines.length
    
    if (points_len>lines_len) {
      for (i=lines_len;i<points_len;i++) {
        lines[i]=document.createElement("div")
        field.appendChild(lines[i])
      }
    }
    else if (points_len<lines_len) {
      for (i=0;i<lines_len-points_len;i++) {
        field.removeChild(lines[i])
      }
      lines.splice(0,i)
    }
    
    for (i=0;i<points_len;i++) {
      lines[i].style.height=points[i][0]+"px"
      lines[i].style.width=points[i][1]+"px"
      lines[i].style.left=points[i][2]+"px"
      lines[i].style.top=points[i][3]+"px"
    }
    
    i=point_len-1
    if (point[i-1][0]==point[i][0] && point[i-1][1]>point[i][1]) point[i][1]--
    else if (point[i-1][1]==point[i][1] && point[i][0]>point[i-1][0]) point[i][0]++
    else if (point[i-1][0]==point[i][0] && point[i-1][1]<point[i][1]) point[i][1]++
    else if (point[i-1][1]==point[i][1] && point[i][0]<point[i-1][0]) point[i][0]--
    
    if (cutend) {
      if (point[0][0]==point[1][0]) {
        if (point[0][1]>point[1][1]) point[0][1]--
        else if (point[0][1]<point[1][1]) point[0][1]++
        if (point[0][1]==point[1][1]) point.splice(0,1)
      }
      else if (point[0][1]==point[1][1]) {
        if (point[1][0]>point[0][0]) point[0][0]++
        else if (point[1][0]<point[0][0]) point[0][0]--
        if (point[1][0]==point[0][0]) point.splice(0,1)
      }
    }
      
    if (mov) mov_t=setTimeout(movement,450/speed)
  }
}