﻿/*****************************************************
Adds the foreach functionality to an array and returns
each item one at a time
******************************************************/
Array.prototype.forEach = function(fn, thisObj) {
  var scope = thisObj || window;
  for (var i = 0, j = this.length; i < j; ++i) {
    if (fn.call != null) {
      fn.call(scope, this[i], i, this);
    }
  }
};

/*******************************************
Sets up the Observer by initalising an array
********************************************/
function Observer() {
  this.fns = [];
}

/*******************************************************
Checks to see if this control and key were added already
********************************************************/
function CheckControlKeyNotAdded(controlname, key, fns) {
  if (fns != null) {
    for (var i = 0; i < fns.length; i++) {
      if (fns[i][0] == key && fns[i][2] == controlname) {
        return false;
      }
    }
  }
  return true;
}

/********************************************************
Extends the Observer object to add two new methods.
The first is a method allow you to subscribe to events
and the second is a method allowing you to fire events
to subscribers. 

The subscribe method works by taking a function (fn) that
is to be your callback function and a key parameter that
describes the type of messages that you would like to
accept. An example of a key would be

demomessages;othermessages

where the Observer would send notifications to the
callback function if messages of that type were fired
The ; character is used to seperate message types and
your method can subscribe to an unlimited number of
message types.

The fire method takes a message and notifies all
subscribers of that message. It does this using the
message which is in JSON format. A sample of a message
would be as follows;

'{ "messagetype" : "demomessages", "index" : 2 }'

This message would be sent to all methods that are subscribed
to demomessages in their key value. The JSON message would also
be fed into these messages so that a single callback function
could take multiple messages and determine which one had been
recieved. The messagetype value must be present in the message.
*********************************************************/
Observer.prototype = {
  subscribe: function(fn, key, controlname) {
    if (CheckControlKeyNotAdded(controlname, key, this.fns)) {
      this.fns.push([key, fn, controlname]);
    }
    else {

      $.grep(this.fns, function(el) {
        if (el[0] == key && el[2] == controlname) {
          el[1] = fn;
        }
      });
    }
    if (bDebug) {
      trace('Control: ' + controlname);
      trace('Accepted Message(s):');
      var keys = key.split(';');
      for (var i = 0; i < keys.length; i++) {
        trace((i + 1) + ' ' + keys[i]);
      }
      delim();
    }
  },
  fire: function(o, thisObj) {
    var scope = thisObj || window;
    this.fns.forEach(
            function(el) {
              var obj = JSON.parse(o);
              var acceptedmessages = el[0].split(';');
              if ($.inArray(obj.messagetype, acceptedmessages) > -1) {
                try {
                  el[1].call(scope, o);
                }
                catch (err) {
                  if (bDebug) {
                    trace(err.description);
                  }
                }
                if (bDebug) {
                  trace('Message Sent');
                  trace('Message type: ' + obj.messagetype);
                  delim();
                }
              }
            }
        );
  }
};

/********************************************
Creates a single Observer object for the page
*********************************************/
var pageobserver = new Observer();

