//paperscript (paperjs)

//'index' page

$(document).ready(function() {

  //common metrics
  var vs = view.size;
  var vsw = vs.width;
  var vsh = vs.height;
  var vss = view.size / 10;
  var vssw = vss.width;
  var vssh = vss.height;

  //pre-load resources
  Promise.all([
    //imgs
    RasterImport_size1('./imgs/phonehand.png'),
    SVGImport_size1('./imgs/arrow-circle-right.svg'),
    SVGImport_size1('./imgs/arrow-circle-left.svg'),
    SVGImport_size1('./imgs/hand-point-right-regular.svg'),
    SVGImport_size1('./imgs/listen-icon.svg'),
    SVGImport_size1('./imgs/iconmonstr-plus-4.svg'),
    SVGImport_size1('./imgs/iconmonstr-minus-4.svg'),
    //clap
    AudioImport_p5("./audio/clap@2/" + ("0" + getRandomInt(1, 2)).slice(-2) + ".mp3"),
    //btn_sounds ==> 9
    AudioImport_p5("./audio/bridgeA/고향돌리도.mp3"),
    AudioImport_p5("./audio/bridgeA/동물소리흉내.mp3"),
    // AudioImport_p5("./audio/bridgeA/동물소리흉내02.mp3"),
    AudioImport_p5("./audio/bridgeA/동물소리흉내03.mp3"),
    AudioImport_p5("./audio/bridgeA/모래야돌아와.mp3"),
    AudioImport_p5("./audio/bridgeA/물소리가있었다.mp3"),
    AudioImport_p5("./audio/bridgeA/우와.mp3"),
    AudioImport_p5("./audio/bridgeA/이거물에넣고해도되요.mp3"),
    AudioImport_p5("./audio/bridgeA/흰수마자돌아와.mp3"),
    AudioImport_p5("./audio/bridgeA/흰수마자어디갔니.mp3"),
    //set_sounds ==> 8
    AudioImport_p5("./audio/path/가을아침.mp3"),
    AudioImport_p5("./audio/path/내나이.mp3"),
    AudioImport_p5("./audio/path/노래.mp3"),
    AudioImport_p5("./audio/path/사랑을했따.mp3"),
    AudioImport_p5("./audio/path/아아아아.mp3"),
    AudioImport_p5("./audio/path/하모니카.mp3"),
    AudioImport_p5("./audio/path/합주.mp3"),
    AudioImport_p5("./audio/path/휘파람.mp3"),
    //beach_sounds ==> 8
    AudioImport("./audio/beach/두드리는01.mp3"),
    AudioImport("./audio/beach/두드리는02.mp3"),
    // AudioImport("./audio/beach/두드리는03.mp3"),
    // AudioImport("./audio/beach/두드리는04.mp3"),
    AudioImport("./audio/beach/두드리는06.mp3"),
    // AudioImport("./audio/beach/모래걸음.mp3"),
    AudioImport("./audio/beach/물소리.mp3"),
    AudioImport("./audio/beach/물장구.mp3"),
    AudioImport("./audio/beach/손장구.mp3"),
    AudioImport("./audio/beach/운더강강술래.mp3"),
    // AudioImport("./audio/beach/웃음.mp3"),
    AudioImport("./audio/beach/젖은모래쓸어내기.mp3"),
    // AudioImport("./audio/beach/천막긁는.mp3"),
    // AudioImport("./audio/beach/풍덩.mp3"),
    //
  ]).then(function(imports) {
    //imgs
    var phonehand = imports[0];
    var anext = imports[1];
    var aprev = imports[2];
    var hand = imports[3];
    var iconsound = imports[4];
    var plus = imports[5];
    var minus = imports[6];
    //clap
    var clap = imports[7];
    //groups
    var group_names = [
      '너',
      '곰곰',
      '레나',
      '은솔',
    ];
    var group_keys = [
      'grp1',
      'grp2',
      'grp3',
      'grp4',
    ];
    //buttons
    var btn_names = [
      '고향',
      '동물1',
      '동물2',
      '모래',
      '물소리',
      '우와',
      '이거',
      '돌아와',
      '어디'
    ];
    var btn_sounds = [
      imports[8],
      imports[9],
      imports[10],
      imports[11],
      imports[12],
      imports[13],
      imports[14],
      imports[15],
      imports[16],
    ];
    //set list
    var set_sounds = {
      '가을아침': imports[17],
      '내나이': imports[18],
      '노래': imports[19],
      '사랑': imports[20],
      '아아': imports[21],
      '하모니카': imports[22],
      '합주': imports[23],
      '휘파람': imports[24]
    };
    //beach list
    var beach_sounds = {
      '두드림1': imports[25],
      '두드림2': imports[26],
      '두드림6': imports[27],
      '물소리': imports[28],
      '물장구': imports[29],
      '손장구': imports[30],
      '강강': imports[31],
      '모래': imports[32]
    };
    var beach_players = {
      '두드림1': [],
      '두드림2': [],
      '두드림6': [],
      '물소리': [],
      '물장구': [],
      '손장구': [],
      '강강': [],
      '모래': [],
    };

    //screen changer
    var nscreen = 6;
    var screens = [];
    var screen_names = {};
    screen_names['start'] = 1;
    screen_names['select'] = 2;
    screen_names['check'] = 3;
    screen_names['bridgeA'] = 4;
    screen_names['path'] = 5;
    screen_names['beach'] = 6;
    var curscreen;
    for (var idx = 0; idx < nscreen; idx++) {
      screens.push(new Layer());
    }

    function changeScreen(page) {
      //pagination buttons
      aprev._activate();
      anext._activate();
      //
      if (page < 1) page = 1;
      if (page > nscreen) page = nscreen;
      curscreen = page;
      for (var idx = 0; idx < nscreen; idx++) {
        //
        if (idx == page - 1) {
          screens[idx].bringToFront();
          top.bringToFront();
          $('.objstring').eq(idx).css('z-index', 1);
          //
          screens[idx].activate();
        } else {
          screens[idx].sendToBack();
          $('.objstring').eq(idx).css('z-index', -1);
        }
      }
      //pagination buttons
      if (curscreen == 1) {
        aprev._deactivate();
      }
      if (curscreen == 2) {
        anext._deactivate();
      }
      if (curscreen == nscreen) {
        anext._deactivate();
      }
    }

    function nextScreen() {
      if (curscreen + 1 <= nscreen) {
        curscreen++;
        changeScreen(curscreen);
      }
    }

    function prevScreen() {
      if (curscreen - 1 > 0) {
        curscreen--;
        changeScreen(curscreen);
      }
    }

    function changeScreenByName(pagename) {
      changeScreen(screen_names[pagename]);
    }

    function getScreenNameNext() {
      if (curscreen + 1 <= nscreen) {
        return Object.keys(screen_names)[curscreen + 1 - 1];
      } else {
        return Object.keys(screen_names)[curscreen - 1];
      }
    }

    function getScreenNamePrev() {
      if (curscreen - 1 > 0) {
        return Object.keys(screen_names)[curscreen - 1 - 1];
      } else {
        return Object.keys(screen_names)[curscreen - 1];
      }
    }

    //top layer
    var top = new Layer(); // new Layer() will be automatically activated at the moment.

    //networking - socket.io
    //var socket = io('http://192.168.1.105:8080');
    var socket = io('http://choir.run:8080');

    //net. connection marker
    var netstat = new Path.Circle({
      center: view.bounds.topRight + [-vssw / 2, +vssw / 2],
      radius: vssw / 4,
      fillColor: 'hotpink',
      strokeWidth: 2,
      strokeColor: 'gray',
      dashArray: [4, 4],
      onFrame: function(event) {
        this.rotate(1);
      }
    });
    netstat.fillColor.alpha = 0;

    //
    socket.on('connect', function() {
      console.log("i' m connected!");
      top.activate();
      netstat.fillColor.alpha = 1;
      socket.on('disconnect', function() {
        console.log("i' m disconnected!");
        top.activate();
        netstat.fillColor.alpha = 0;
      });
    });

    //page change - prev. page
    aprev.addTo(project);
    aprev.scale(vsw / 4);
    aprev.position = [0, 0]; //reset position, before relative positioning !!
    aprev.translate([vssw, vssw * 2.5]);
    aprev.fillColor = 'pink';
    aprev._socket = socket;
    aprev._isactive = false;
    aprev._activate = function() {
      this._isactive = true;
      this.opacity = 1;
    }
    aprev._deactivate = function() {
      this._isactive = false;
      this.opacity = 0.3;
    }
    aprev.onClick = function() {
      if (this._isactive == true) {
        prevScreen();
      }
    };

    //page change - next. page
    anext.addTo(project);
    anext.scale(vsw / 4);
    anext.position = [0, 0]; //reset position, before relative positioning !!
    anext.translate([vssw * 9, vssw * 2.5]);
    anext.fillColor = 'pink';
    anext._socket = socket;
    anext._isactive = false;
    anext._activate = function() {
      this._isactive = true;
      this.opacity = 1;
    }
    anext._deactivate = function() {
      this._isactive = false;
      this.opacity = 0.3;
    }
    anext.onClick = function() {
      if (this._isactive == true) {
        nextScreen();
      }
    };

    //title background
    new Path.Rectangle({
      point: [vssw * 2, vssw * 1.5],
      size: [vssw * 6, vssw * 2],
      fillColor: 'white',
      radius: 30,
    }).opacity = 0.3;

    //screen #1 - 'home'
    changeScreen(1);
    new Path.Rectangle([0, 0], vs).fillColor = '#999';

    //hello, screen.
    phonehand.addTo(project);
    phonehand.scale(vsw / 1.5);
    phonehand.position = view.center;
    //phonehand.position.y -= vssh;

    //screen #2 - 'select'

    changeScreen(2);
    new Path.Rectangle([0, 0], vs).fillColor = '#3333ff'; //;

    //group select buttons
    var group_selected = undefined; //key
    for (var row = 0; row < 2; row++) {
      for (var col = 0; col < 2; col++) {
        var idx = row * 2 + col;
        var c = new Path.Circle({
          center: [col * vssw * 3 + vssw * 3, row * vssw * 3 + vssw * 6],
          radius: vssw * 0.8,
          fillColor: new Color({
            hue: getRandom(0, 180),
            saturation: 1,
            brightness: 1
          }),
          _idx: idx,
          onClick: function() {
            group_selected = group_keys[this._idx];
            console.log(group_selected);
            //next screen.
            changeScreen(3);
          }
        });
        new PointText({
          point: c.bounds.topLeft + [0, -5],
          content: group_names[idx],
          fontSize: '1em',
          fontWeight: 'bold',
          fillColor: c.fillColor
        });
      }
    }

    //screen #3 - check
    changeScreen(3);
    new Path.Rectangle([0, 0], vs).fillColor = '#393';

    //TODO: info text.
    new PointText({
      content: "네트워크 테스트!",
      point: view.center + [-vssw * 3, -vssw * 2],
      fontWeight: 'bold',
      fontSize: '2em',
      fillColor: 'gold'
    });
    new PointText({
      content: "사운드 테스트!",
      point: view.center + [-vssw * 3, vssw * 0],
      fontWeight: 'bold',
      fontSize: '2em',
      fillColor: 'pink'
    });
    new PointText({
      content: "동그라미 터치!",
      point: view.center + [-vssw * 3, vssw * 2],
      fontWeight: 'bold',
      fontSize: '2em',
      fillColor: 'red'
    });
    new Path.Circle({
      center: view.center,
      radius: vsw / 4,
      fillColor: 'white',
      opacity: 0.5,
      onClick: function() {
        clap.play();
      }
    });

    //screen #4 - bridgeA
    changeScreen(4);
    new Path.Rectangle([0, 0], vs).fillColor = '#333';

    //sound list
    var buttons = [];

    for (var row = 0; row < 3; row++) {
      for (var col = 0; col < 3; col++) {
        var idx = row * 3 + col;

        //play/stop button (networked between groups)
        var c = new Group([
          new Path.Circle({
            center: [col * vssw * 2.5 + vssw * 2, row * vssw * 2.3 + vssw * 5.5],
            radius: vssw * 0.8,
            fillColor: new Color({
              hue: getRandom(0, 180),
              saturation: 1,
              brightness: 1
            }),
            _socket: socket,
            _key: btn_names[idx],
            _player: btn_sounds[idx],
            _playcount: 0,
            _init: function() {
              var that = this;
              this._socket.on('sound', function(msg) {
                if (msg.group == group_selected && msg.name == that._key) {
                  if (msg.action == 'start') {
                    that._playstart();
                    that._playcount++;
                  }
                }
              });
              this.nextSibling.opacity = 0; //marker off!
              this._player.playMode('restart');
            },
            _playstart: function() {
              // play (re-)start now!
              this._player.play();
              this.nextSibling.opacity = 1; //marker on!
              var that = this;
              this._player.onended(function() {
                if (that._playcount > 0) {
                  that._playcount--;
                  if (that._playcount == 0) { // only do this, when it is finally stopped.
                    that.nextSibling.opacity = 0; //marker off!
                  }
                }
              });
            },
            _playstop: function() {
              this._player.stop();
              this.nextSibling.opacity = 0; //marker off!
            },
            onMouseDown: function() {
              //
              this._playstart();
              this._playcount++;
              //
              this._socket.emit('sound', {
                name: this._key,
                action: 'start',
                group: group_selected
              });
            }
          }),
          //the marking ring around the button
          new Path.Circle({
            center: [col * vssw * 2.5 + vssw * 2, row * vssw * 2.3 + vssw * 5.5],
            radius: vssw * 1,
            strokeWidth: 5,
            strokeColor: 'white'
          })
        ]);
        c.firstChild._init();
        buttons.push(c);
        //labels
        new PointText({
          point: c.firstChild.bounds.topLeft + [0, -5],
          content: btn_names[idx],
          fontSize: '2em',
          fontWeight: 'bold',
          fillColor: c.firstChild.fillColor
        });
      }
    }
    //speed controller - frame
    new Group({
      children: [
        new Path.Rectangle({
          point: [vsw - vssw * 1.5, vssh * 2.5],
          size: [vssw, vssh * 6],
          radius: 20,
        }),
        new Path.Rectangle({
          point: [vsw - vssw * 1.5, vssh * 2.5],
          size: [vssw, vssh * 3],
          fillColor: 'blue'
        }),
        new Path.Rectangle({
          point: [vsw - vssw * 1.5, vssh * 2.5 + vssh * 3],
          size: [vssw, vssh * 3],
          fillColor: 'gold'
        }),
      ],
      clipped: true
    });
    //speed controller - knob
    var knob = new Path.Circle({
      center: [vsw - vssw, vssh * 2.5 + vssw * 0.5],
      radius: 20,
      fillColor: 'white',
      _start_y: vssh * 2.5 + vssw * 0.5,
      _end_y: vssh * 2.5 + vssh * 6 - vssw * 0.5,
      onMouseDrag: function(event) {
        if (event.point.y > this._end_y) {
          this.position.y = this._end_y;
        } else if (event.point.y < this._start_y) {
          this.position.y = this._start_y;
        } else {
          this.position.y = event.point.y;
        }
        var control = map(this.position.y, [this._start_y, this._end_y], [-1, 1]);
        //playback speed change.. (perform the effect)
        buttons.forEach(function(item) {
          item.firstChild._player.rate(Math.pow(5, control));
        });
      }
    });
    //initial position of the knob. 0 means 1 (Math.pow(XXX, 0) == 1)
    knob.position.y = map(0, [-1, 1], [knob._start_y, knob._end_y]);
    //stop button
    var stopbtn = new Group({
      _socket: socket,
      children: [
        new Path.Circle({
          center: [vssw * 2.7 + vssw * 2, 2.5 * vssw * 2.7 + vssw * 6],
          radius: vssw * 0.8
        })
      ],
      onMouseDown: function() {
        buttons.forEach(function(item) {
          item.firstChild._playstop();
          item.firstChild._playcount = 0;
        });
        //
        this._socket.emit('sound', {
          name: 'stop',
          action: 'stop',
          group: group_selected
        });
      }
    });
    //label
    stopbtn.addChild(new PointText({
      point: stopbtn.bounds.topLeft + [0, -5],
      content: 'stop',
      fontSize: '2em',
      fontWeight: 'bold'
    }));
    stopbtn.fillColor = 'red';
    //'stop' handler
    socket.on('sound', function(msg) {
      if (msg.action == 'stop') {
        buttons.forEach(function(item) {
          item.firstChild._playstop();
          item.firstChild._playcount = 0;
        });
      }
    });

    //screen #5 - path
    changeScreen(5);
    new Path.Rectangle([0, 0], vs).fillColor = '#333';

    //
    for (var row = 0; row < 8; row++) {
      for (var col = 0; col < 1; col++) {
        var idx = row * 1 + col;

        //play/stop/marker button (networked between groups)
        var c = new Group({
          children: [
            //play button
            new Path.Rectangle({
              point: [vssw * 1.4, row * vssw * 1.5 + vssw * 4.5],
              radius: vssw * 0.4,
              size: [vssw * 2.8, vssw * 0.8],
              fillColor: new Color({
                hue: getRandom(20, 60),
                saturation: 1,
                brightness: 1
              }),
              onMouseDown: function() {
                var par = this.parent;
                par._player.play();
                par._playcount++;
                par.lastChild.fillColor = 'white'; //marker on!
                par._player.onended(function() {
                  if (par._playcount > 0) {
                    par._playcount--;
                    if (par._playcount == 0) { // only do this, when it is finally stopped.
                      par.lastChild.fillColor = 'black'; //marker off!
                    }
                  }
                });
                //
                par._socket.emit('sound', {
                  name: par._key,
                  action: 'start',
                  group: 'path'
                });
              }
            }),
            //stop button
            new Path.Rectangle({
              point: [vssw * 4.8, row * vssw * 1.5 + vssw * 4.5],
              radius: vssw * 0.4,
              size: [vssw * 2.8, vssw * 0.8],
              fillColor: new Color({
                hue: getRandom(120, 250),
                saturation: 1,
                brightness: 1
              }),
              onMouseDown: function() {
                var par = this.parent;
                par._player.stop();
                par._playcount = 0;
                par.lastChild.fillColor = 'black'; //marker off!
                //
                par._socket.emit('sound', {
                  name: par._key,
                  action: 'stop',
                  group: 'path'
                });
              }
            }),
            //playing marker
            new Path.Circle({
              center: [vssw * 8.5, row * vssw * 1.5 + vssw * 4.9],
              radius: vssw * 0.4,
              fillColor: 'black'
            })
          ],
          _socket: socket,
          _key: Object.keys(set_sounds)[idx],
          _player: set_sounds[Object.keys(set_sounds)[idx]],
          _playcount: 0,
          _init: function() {
            this._player.playMode('restart');
          }
        });
        c._init();
        //label
        new PointText({
          point: c.firstChild.bounds.topLeft + [0, -5],
          content: Object.keys(set_sounds)[idx],
          fontSize: '1em',
          fontWeight: 'bold',
          fillColor: 'white'
        });
      }
    }

    //screen #6 - beach
    changeScreen(6);
    new Path.Rectangle([0, 0], vs).fillColor = '#333';

    //
    for (var row = 0; row < 8; row++) {
      for (var col = 0; col < 1; col++) {
        var idx = row * 1 + col;

        //play/stop/playcount/faster/slower button (networked between groups)
        var c = new Group({
          children: [
            //play button
            new Path.Rectangle({
              point: [vssw * 0.8, row * vssw * 1.5 + vssw * 4.5],
              radius: vssw * 0.4,
              size: [vssw * 1.6, vssw * 0.8],
              fillColor: new Color({
                hue: getRandom(20, 60),
                saturation: 1,
                brightness: 1
              }),
              onMouseDown: function(event) {
                var par = this.parent;
                par._players.push(par._player.start()._source); // start playbacks and collect their '_source's..
                par._playcount++;
                par.children.playcounter.content = '' + par._playcount;
                //
                par._socket.emit('sound', {
                  name: par._key,
                  action: 'start',
                  group: 'beach'
                });
              }
            }),
            //stop button
            new Path.Rectangle({
              point: [vssw * 2.8, row * vssw * 1.5 + vssw * 4.5],
              radius: vssw * 0.4,
              size: [vssw * 1.6, vssw * 0.8],
              fillColor: new Color({
                hue: getRandom(120, 250),
                saturation: 1,
                brightness: 1
              }),
              onMouseDown: function() {
                var par = this.parent;
                if (par._players.length > 0) {
                  (par._players.shift()).stop();
                  par._playcount--;
                  par.children.playcounter.content = '' + par._playcount;
                }
                //
                par._socket.emit('sound', {
                  name: par._key,
                  action: 'stop',
                  group: 'beach'
                });
              }
            }),
            //playcounter
            new PointText({
              name: 'playcounter',
              content: '' + 0,
              point: [vssw * 4.8, row * vssw * 1.5 + vssw * 4.5 + vssw * 0.7],
              fillColor: 'white',
              fontSize: '2em',
              fontWeight: 'bold'
            }),
            //faster button
            new Path.Rectangle({
              point: [vssw * 5.8, row * vssw * 1.5 + vssw * 4.5],
              radius: vssw * 0.4,
              size: [vssw * 1.6, vssw * 0.8],
              fillColor: new Color({
                hue: getRandom(20, 60),
                saturation: 1,
                brightness: 1
              }),
              onMouseDown: function() {
                var par = this.parent;
                if (par._players.length > 0) {
                  par._players[par._players.length - 1].playbackRate.value += 0.2;
                }
                //
                par._socket.emit('sound', {
                  name: par._key,
                  action: 'faster',
                  group: 'beach'
                });
              }
            }),
            //slower button
            new Path.Rectangle({
              point: [vssw * 7.8, row * vssw * 1.5 + vssw * 4.5],
              radius: vssw * 0.4,
              size: [vssw * 1.6, vssw * 0.8],
              fillColor: new Color({
                hue: getRandom(120, 250),
                saturation: 1,
                brightness: 1
              }),
              onMouseDown: function() {
                var par = this.parent;
                if (par._players.length > 0) {
                  par._players[par._players.length - 1].playbackRate.value -= 0.2;
                }
                //
                par._socket.emit('sound', {
                  name: par._key,
                  action: 'slower',
                  group: 'beach'
                });
              }
            })
          ],
          _socket: socket,
          _key: Object.keys(beach_sounds)[idx],
          _player: beach_sounds[Object.keys(beach_sounds)[idx]],
          _players: beach_players[Object.keys(beach_players)[idx]],
          _playcount: 0,
          _init: function() {
            this._player.loop = true;
            this._player.retrigger = true;
            //socket io event handling..
            var that = this;
            this._socket.on('sound', function(msg) {
              if (msg.group == 'beach' && msg.name == that._key) {
                if (msg.action == 'start') {
                  that._players.push(that._player.start()._source); // start playbacks and collect their '_source's..
                  that._playcount++;
                  that.children.playcounter.content = '' + that._playcount;
                } else if (msg.action == 'stop') {
                  if (that._players.length > 0) {
                    (that._players.shift()).stop();
                    that._playcount--;
                    that.children.playcounter.content = '' + that._playcount;
                  }
                } else if (msg.action == 'faster') {
                  if (that._players.length > 0) {
                    that._players[that._players.length - 1].playbackRate.value += 0.2;
                  }
                } else if (msg.action == 'slower') {
                  if (that._players.length > 0) {
                    that._players[that._players.length - 1].playbackRate.value -= 0.2;
                  }
                }
              }
            });
          }
        });
        c._init();
        //label
        new PointText({
          point: c.firstChild.bounds.topLeft + [0, -5],
          content: Object.keys(beach_sounds)[idx],
          fontSize: '1em',
          fontWeight: 'bold',
          fillColor: 'white'
        });
      }
    }

    //home
    changeScreen(1);

    //reveal the curtain.
    $('#page-loading').css('z-index', -1);

    //network event handlers

    //event: 'sound'
    socket.on('sound', function(sound) {
      if (sound.name == 'clap') {
        if (sound.action == 'start') {
          clap.start();
        }
      }
    });

  });

});
