﻿var Quek = new Class({
  initialize: function(id, name) {
    this.id = id;
    this.name = name;
    this.flashId = "flash_" + id;
    this.isSelf = id == "self";
    this.mood = "neutraal";
    this.triggers = [];
    this.initHtml();
    this.hasGravity = false;
  },

  initHtml: function() {
    this.elements = {};
    var quek = $("quek").clone().injectAfter("quek");

    this.elements.quek = quek;
    this.elements.quek.id = "quek_" + this.id;
    this.elements.name = quek.getElement("h2");
    this.elements.flash = quek.getElement(".flash");
    this.elements.flashContainer = quek.getElement(".flashContainer");
    this.elements.follow_once = quek.getElement(".follow_once");
    this.elements.follow = quek.getElement(".follow");
    this.elements.follows = quek.getElement(".follows");
    this.elements.balloon = quek.getElement(".balloon");
    this.elements.textWrap = quek.getElement(".textWrap");
    this.elements.say = quek.getElement(".say");
    this.elements.inputField = quek.getElement(".inputField");
    this.elements.quekForm = quek.getElement(".quekform");
    this.elements.gift = quek.getElement(".gift");
    this.elements.soundLinks = quek.getElements(".sound-link");
    this.elements.actionMenu = quek.getElement(".action-menu");
    this.elements.selfActions = quek.getElement(".self-actions");
    this.elements.urlInput = quek.getElement(".urlInput");
    this.elements.gotoUrl = quek.getElement(".urlInput .input");
    this.elements.giveBeer = quek.getElement(".give-beer");
    this.elements.kiss = quek.getElement(".kiss");
    this.elements.urlInputWrapper = quek.getElement(".urlInputWrapper");
    this.elements.linkGo = quek.getElement(".link-go");
    this.elements.followed = quek.getElement(".followed");

    this.elements.follow_once.addEvent("click", this.handleArrowClick.bindWithEvent(this));
    this.elements.quekForm.addEvent("submit", this.handleSay.bindWithEvent(this));
    this.elements.soundLinks.addEvent("click", this.setSound.bindWithEvent(this));
    this.elements.follow.addEvent("click", this.follow.bindWithEvent(this));
    this.elements.follows.addEvent("click", this.stopFollow.bindWithEvent(this));
    this.elements.giveBeer.addEvent("click", this.giveBeer.bindWithEvent(this));
    this.elements.kiss.addEvent("click", this.kiss.bindWithEvent(this));
    this.elements.linkGo.addEvent("click", this.toggleUrlInput.bindWithEvent(this));
    this.elements.inputField.addEvent("focus", this.setTextInputFocussed.bind(this, true));
    this.elements.inputField.addEvent("blur", this.setTextInputFocussed.bind(this, false));
    this.elements.followed.addEvent("click", this.follow.bindWithEvent(this));

    var flashUrl = this.isSelf ? "/flash/myQuekSound.swf" : "/flash/quekSound.swf";
    new Swiff(flashUrl, {
      id: this.flashId,
      width: 150,
      height: 150,
      container: this.elements.flash
    });

    this.elements.flashObject = (Browser.Engine.trident ? window : document)[this.flashId];
    this.elements.flashObject.onfocus = function() { this.blur() };

    var self = this;
    var mouseoverTimer = null;
    this.elements.quek.addEvents({
      "mouseenter": function() {
        $clear(mouseoverTimer);
        self.showActionMenu();
      },
      "mouseleave": function() {
        mouseoverTimer = self.hideActionMenu.delay(600, self);
      }
    });

    $$(this.elements.quekForm, this.elements.actionMenu, this.elements.balloon).fade('hide');

    if (this.isSelf)
      this.initSelf();
  },
  setTextInputFocussed: function(focussed) {
    this.textInputFocussed = focussed;
  },
  toggleUrlInput: function() {
    this.setUrlInput(!this.urlInputActive);
  },
  setUrlInput: function(active) {
    this.urlInputActive = active;

    if (this.urlInputActive) {
      this.elements.urlInputWrapper.setStyle('display', 'block');
      this.elements.urlInput.tween('right', '-15px');
    }
    else {
      this.elements.urlInput.tween('right', '225px');
      setTimeout(function() { QuekClient.queks.self.elements.urlInputWrapper.setStyle('display', 'none'); }, 500)
    }
  },

  follow: function() {
    this.setFollowed(!this.isFollowed);
    var followedQuek = this.isFollowed ? this : null;

    if (this.loggedInFuntionality())
      QuekClient.queks.self.setFollowedQuek(followedQuek);
  },

  stopFollow: function(event) {
    event.stop();
    this.setFollowedQuek(null);
  },

  setFollowed: function(isFollowed) {
    this.isFollowed = isFollowed;
    if (isFollowed) {
      this.elements.quek.addClass("isFollowed");
      this.elements.followed.title = this.name + " niet meer volgen";
    }
    else {
      this.elements.quek.removeClass("isFollowed");
    }
  },

  setFollowedQuek: function(quek) {
    if (this.followedQuek)
      this.followedQuek.setFollowed(false);

    this.followedQuek = quek;
    if (quek) {
      this.elements.quek.addClass("following");
      this.elements.follows.title = "Je volgt nu " + quek.name;
      if (quek.url && this.loggedInFuntionality())
        QuekClient.queks.self.sendUrl(quek.url);
    }
    else {
      this.elements.quek.removeClass("following");
    }
  },

  initSelf: function() {
    this.elements.quek.addClass("myQuek");
    this.elements.quek.title = this.name;
    var windowSize = window.getSize();
    var quekSize = this.elements.quek.getSize();
    var x = $random(0, windowSize.x - 200);
    var y = $random(150, windowSize.y - 200);
    var z = 0;

    this.sendPosition(x, y, z);
    this.makeDraggable();

    this.addTrigger(["neutraal", "saai", "stil", "neutral", "boring", "silent", "stop"], "mood", "neutraal");
    this.addTrigger(["zwaaien", "zwaai", "hoi", "gezwaaid", "hallo", "joehoe", "tee-hi", "hello"], "mood", "zwaaien");
    this.addTrigger(["schateren", "schater", "rofl", "lachen", "lach", "laugh", "laughing"], "mood", "schateren");
    this.addTrigger(["kussen", "kus", "kiss", "kissing"], "mood", "kussen");
    this.addTrigger(["gekust", "gekust", "kissed"], "mood", "gekust");
    this.addTrigger(["grijns", "grijnzen", "grijnst", "gegrijnst", "lol", "grin"], "mood", "grijns");
    this.addTrigger(["verbaasd", "verbazen", "vreemd", "surprised", "weird"], "mood", "verbaasd");
    this.addTrigger(["praten", "praat", "zeg", "zeggen", "blabla", "talk"], "mood", "praten");
    this.addTrigger(["ontploft", "ontplof", "lul", "explode", "bomb"], "mood", "ontploft");
    this.addTrigger(["verdrietig", "huilen", "cry", "crying"], "mood", "verdrietig");
    this.addTrigger(["boos", "kwaad", ":x", "angry"], "mood", "boos");
    this.addTrigger(["moe", "vermoeid", "gaap", "yawn", "tired"], "mood", "moe");
    this.addTrigger(["fluiten", "fluit", "whistle", "whistling"], "mood", "fluiten");
    this.addTrigger(["draaien", "draai", "turn", "twist"], "mood", "draaien");
    this.addTrigger(["terugdraaien", "draaiterug"], "mood", "terugdraaien");
    this.addTrigger(["macarena", "dansen", "dance", "dancing"], "mood", "macarena");
    this.addTrigger(["moonwalk", "billyjean", "jackson"], "mood", "moonwalk");
    this.addTrigger(["bier", "beer"], "beer");
    this.addTrigger(["kussen", "kus", "kiss"], "kiss");
  },
  showActionMenu: function() {
    this.elements.quek.setStyle('z-index', 99);
    this.elements.actionMenu.fade('in');
    this.elements.quekForm.fade('in');
  },
  hideActionMenu: function() {
    if (!this.textInputFocussed && !this.urlInputActive) {
      this.elements.quek.setStyle('z-index', 0);
      this.elements.actionMenu.fade('out');
      this.elements.quekForm.fade('out');
    }
  },

  updateDragLimit: function() {
    if (this.dragger) this.dragger.options.limit = this.createDragLimit();
  },

  createDragLimit: function() {
    var size = window.getSize();
    return { x: [0, size.x - 200], y: [0, size.y - 200] };
  },

  toggleSlide: function(shouldHaveGravity) {

    if (!$defined(shouldHaveGravity))
      shouldHaveGravity = !this.doesSlide;

    if (shouldHaveGravity)
      this.elements.quek.addClass('sliding')
    else
      this.elements.quek.removeClass('sliding')

    // TODO check of dit volledig Drag afbouwt
    if (this.dragger) {
      this.dragger.detach();
    }

    var D = shouldHaveGravity ? Drag.Flick : Drag;

    //if(this.isSelf)
    this.dragger = new D(this.elements.quek, {
      handle: this.elements.flashContainer,
      onStart: this.handleDrag.bind(this),
      gravity: { x: 0, y: 0.6 },
      friction: 0.05,
      bounce: 0.8,
      limit: this.createDragLimit()
    });

    this.dragger.addEvent(shouldHaveGravity ? 'moveEnd' : 'complete', this.handleDrop.bind(this));

    if (shouldHaveGravity) this.dragger.pusher.start(0.1, 0.1);

    this.doesSlide = shouldHaveGravity;

    //zwaartekracht weer uitgezet? Dan krijgt elke Quek weer een default dragger, maar dat willen we niet,
    //want alleen je eigen Quek moet draggable zijn. Dus weer detachen.
    if (!shouldHaveGravity && !this.isSelf)
      this.dragger.detach();
  },

  toggleGravity: function(hasGravity) {
    return this.toggleSlide(hasGravity);
  },

  makeDraggable: function() {
    this.toggleSlide(false);
  },

  handleDrop: function() {
    var pos = this.elements.quek.getPosition();
    var z = 0;
    this.sendPosition(pos.x, pos.y, z);

    $("eventCatcher").setStyle('display', 'none');

    //ben je een andere Quek die klaar is met vallen uit zwaartekracht?
    //dragger uitzetten, want je mag niet gedragged worden.
    if (!this.isSelf)
      this.dragger.detach();
  },

  setName: function(name) {
    this.name = name;
    this.elements.follow.set('title', 'Volg ' + name);
    this.elements.name.set('html', name);
  },

  setPosition: function(x, y, z) {
    var windowSize = window.getSize();
    var quekSize = this.elements.quek.getSize();

    var limitY = windowSize.y;

    x = x.toInt().limit(0, windowSize.x - quekSize.x);
    y = y.toInt().limit(0, limitY - quekSize.y);

    var currentPosition = this.elements.quek.getPosition();

    if (currentPosition.x !== x || currentPosition.y !== y || QuekClient.hasGravity) {
      if (QuekClient.hasGravity) {
        y = windowSize.y - 200;
        this.elements.quek.morph({ left: x, top: currentPosition.y });
        this.createDragLimit();
      }

      else {
        this.elements.quek.set('morph', { duration: 1000, transition: 'elastic:out' });
        if (this.dragger && this.dragger.pusher)
          this.dragger.pusher.cancel();
        this.elements.quek.morph({ left: x, top: y });
      }
    }
  },

  sendPosition: function(x, y, z) {
    this.setPosition(x, y, z);
    var position = x + " " + y + " " + z;
    Multiplayer.send({ "position": position });
  },

  setMood: function(mood) {
    if (mood == "draaien" && this.isTurned)
      mood = "terugdraaien";
    this.isTurned = mood == "draaien";

    this.mood = mood;

    this.elements.flashObject.TGotoLabel("_root", mood);
  },

  sendMood: function(mood) {
    this.fireEvent("mood", mood);
  },

  setText: function(text) {
    $clear(this.sayTimeout);

    if (text) {
      var say = this.elements.say;
      say.setStyle('top', 0);
      this.logText(text, this.name);
      var textWrap = this.elements.textWrap;

      //er zou nog een animatie kunnen lopen. Die moeten we cancellen.
      say.get('tween').cancel();
      this.elements.balloon.get('morph').cancel();
      this.elements.balloon.setStyle('display', 'block');

      say.set('html', unescape(text).replace(/</g, "&lt;"));
      var diff = textWrap.getHeight() - say.getHeight()
      var animDuration = 4000;
      if (diff < 0) {
        animDuration = 1000 * (-diff / 20);
        say.set('tween', { duration: animDuration });
        (function() { say.tween('top', [0, diff]) }).delay(1000);
        animDuration = animDuration + 5000;
      }
      this.sayTimeout = this.setText.delay(animDuration, this, "");
      this.elements.balloon.fade("in");
    }
    else {
      if (this.mood == "praten") {
        this.setMood("neutraal")
      }
      var balloon = this.elements.balloon;
      balloon.set('morph', { link: 'chain' });
      balloon.morph({ 'opacity': 0 });
      balloon.morph({ 'display': 'none' }); //waarom werkt dit niet met setStyle? omdat je aangeeft dat je morph gaat chainen?
    }
  },

  sendText: function(text) {
    this.setText(text);
    Multiplayer.send({ "say": escape(text) });
  },

  logText: function(text, name) {
    if (this.id == "self") {
      //      alert(text + " " + name);
    }
  },

  //bij ontvangen van de url
  setUrl: function(url) {
    var host = location.hostname;
    if (url.indexOf("http://" + host) > -1 || url.indexOf(host) == 0 || url == "http://")
      url = "";

    this.url = url;

    if (this.url)
      this.changeUrl(url);
    else
      this.emptyUrl();

    if (this.isFollowed && this.loggedInFuntionality())
      QuekClient.queks.self.sendUrl(url);

  },

  changeUrl: function(url) {
    if (this.isSelf) {
      this.setUrlInput(false);
      $(document.body).addClass("otherSite");
      $("otherSite").set('src', url);
    }
    else {
      this.elements.quek.addClass("other-site");
      var follow_once = this.elements.follow_once;
      follow_once.set({
        'morph': { transition: 'bounce:out', duration: 500 },
        'html': this.getDomainFromUrl(url),
        'href': url,
        'title': 'volg ' + this.name + ' naar: ' + url
      });
      follow_once.morph({ 'top': 145 });
    }
    window.location = "#";
    QuekClient.repositionQueks();
  },

  emptyUrl: function() {
    if (this.isSelf) {
      this.setUrlInput(false);
      $(document.body).removeClass("otherSite");
      $("otherSite").set('src', '');
    }
    else {
      this.elements.quek.removeClass("other-site");
      var follow_once = this.elements.follow_once;
      follow_once.set({
        'morph': { transition: 'bounce:out', duration: 500 },
        'html': "",
        'href': "#",
        'title': ""
      });

      follow_once.morph({ 'top': 130 });
    }
    window.location = "#";
  },

  getDomainFromUrl: function(url) {
    var domain = url.contains('www.') ? url.substring(11) : url.substring(7);
    domain = domain.contains('.') ? domain.substring(0, domain.indexOf('.')) : domain;
    if (domain.length > 13)
      return domain.substring(0, 13) + "...";
    else
      return domain;
  },

  giveBeer: function(event) {
    event.stop();
    if (this.loggedInFuntionality("ik wil geen bier van vreemden"))
      QuekClient.queks.self.fireEvent("beer", this.name);
  },

  kiss: function(event) {
    event.stop();
    if (this.loggedInFuntionality("ik wil geen zoen van vreemden"))
      QuekClient.queks.self.fireEvent("kiss", this.name);
  },

  sendUrl: function(url) {
    this.fireEvent("url", url);
  },

  setSound: function(event) {
    event.stop();
    var soundIsOff = this.elements.quek.hasClass("sound-off");
    if (soundIsOff) {
      this.setMood("sound");
      this.elements.quek.removeClass("sound-off");
      event.target.title = "geluid uit";
    }
    else {
      this.setMood("nosound");
      this.elements.quek.addClass("sound-off");
      event.target.title = "geluid aan";
    }
  },

  fireEvent: function(name, value) {
    var event = {};
    event[name] = value;
    Multiplayer.send(event);
    this.handleEvent(name, value);
  },

  handleEvent: function(name, value) {
    switch (name) {
      case "name":
        this.setName(value);
        break;
      case "say":
        this.setText(value);
        break;
      case "position":
        var position = value.split(" ");
        this.setPosition(position[0], position[1], position[2]);
        break;
      case "mood":
        this.setMood(value);
        break;
      case "url":
        this.setUrl(value);
        break;
      case "beer":
        new Special.Gift(this, value, name);
        break;
      case "kiss":
        new Special.Kiss(this, value);
        break;
      case "disconnect":
        this.disconnect();
        break;
    }
  },

  handleDrag: function() {
    // prevent 'leaking' mousemove events to the iframe
    $("eventCatcher").setStyle('display', 'block');
  },


  handleSay: function(event) {
    event.stop();
    var showText = true;
    var text = this.elements.inputField.get('value');
    var url = text.match(/^http:\/\/\S+/); ;
    if (url) {
      this.sendUrl(url[0]);
      this.setFollowedQuek(null);
    }

    this.checkTriggers(text);

    this.elements.inputField.erase('value');

    if (showText)
      this.sendText(text);
  },

  addTrigger: function(triggers, name, value) {
    var regexp = new RegExp("\\b(" + triggers.join("|") + ")\\b", "i");
    this.triggers.push({ regexp: regexp, name: name, value: value });
  },

  checkTriggers: function(text) {
    var target;
    var matchedTriggers = this.triggers.filter(function(trigger) { return text.test(trigger.regexp); });
    if (matchedTriggers.length == 0)
      return;

    var trigger = matchedTriggers[0];
    if (!$chk(trigger.value)) {
      if (target == undefined)
        target = QuekClient.getTarget(text);

      if (target && target != this)
        trigger.value = target.name;
      else
        return;
    }

    this.fireEvent(trigger.name, trigger.value);
  },

  handleArrowClick: function(event) {
    event.stop();
    var url = this.elements.follow_once.href;
    var self = QuekClient.queks.self;
    self.sendUrl(url);
    self.setFollowedQuek(null);
  },

  savePosition: function() {
    this.savedPosition = this.elements.quek.getPosition();
    this.savedPosition.z = this.elements.quek.getStyle("z-index");
  },

  revertPosition: function() {
    if (this.savedPosition)
      this.setPosition(this.savedPosition.x, this.savedPosition.y, this.savedPosition.z);
  },

  moveTo: function(target, offsetX, offsetY, offsetZ) {
    var position = target.elements.quek.getPosition();
    position.z = target.elements.quek.getStyle("z-index");

    position.x += offsetX || 0;
    position.y += offsetY || 0;
    position.z += offsetZ || 0;

    this.setPosition(position.x, position.y, position.z);
  },

  loggedInFuntionality: function(msg) {
    if (QuekClient.queks.self) {
      return true;
    }
    else {
      this.setText(msg);
      return false;
    }
  },

  disconnect: function() {
    this.elements.quek.dispose();
  }
});
