function Session(cwsObj)  {
  var scormObj = new ScormInterface(cwsObj);
  var fileDataObj = new FileDataInterface(cwsObj);
  var nullObj = new NullInterface(cwsObj);
  var currentDataObj = null;
  var sessionStart = null;
  this.scormActive = false;
  this.loginDisplayType = null;
  this.registerDisplayType = null;
  this.initialized = false;

  this.initialize = function()  {
    sessionStart = new Date;
    var useNullDataInterface = false;
    if (cwsObj.browse)  {
      useNullDataInterface = true;
    }
    else  {
      this.scormActive = scormObj.initialize();
      if (this.scormActive)  {
        currentDataObj = scormObj;
        var scormUser = new User(cwsObj);
        var userDataSet = currentDataObj.setUserData(scormUser);
        if (userDataSet) {
          cwsObj.user = scormUser;
          this.initialized = true;
          cwsObj.launchKlo(cwsObj.currentKloNum);
        }
      }
      else  {
        if (cwsObj.useFileDataInterface)  {
          fileDataObj.initialize();
        }
        else  {
          useNullDataInterface = true;
        }
      }
    }
    if (useNullDataInterface) {
      currentDataObj = nullObj;
      cwsObj.user = new User(cwsObj);
      this.initialized = true;
      cwsObj.launchKlo(cwsObj.currentKloNum);
    }
  }
  this.fileDataInitializationComplete = function(error)  {
    if (!error) {
      this.initialized = true;
      currentDataObj = fileDataObj;
      this.loginDisplayType.loadUserInterface(this.loginDisplayType.userInterface);
      this.registerDisplayType.loadUserInterface(this.registerDisplayType.userInterface);
      if (cwsObj.autoLogin) {
        doAutoLogin();
      }
      else  {
        cwsObj.contentFrameObj.location.href = cwsObj.rootPath + "data/" + cwsObj.lang + "/login.htm";
      }
    }
    else  {
      this.setSessionState(3);
    }
  }
  this.intializeCdCompletion = function()  {
    sessionStart = new Date;
    this.scormActive = scormObj.initialize();
    if (this.scormActive)  {
      currentDataObj = scormObj;
      var scormUser = new User(cwsObj);
      if (currentDataObj.setUserData(scormUser)) {
        cwsObj.user = scormUser;
        this.initialized = true;
        return true;
      }
      else  {
        alert("An error occured while communicating to the LMS.\nYou will not be able to enter in a Completion Code.");
      }
    }
    else  {
      alert("We are unable to connect to a SCORM compliant LMS.\nAs a result, you will not be able to enter in your completion code.");
    }
    return false;
  }
  this.setCourseComplete = function()  {
    if (this.initialized) {
      if (cwsObj.user.courseScore > -1) {
        cwsObj.user.courseStatus = "passed";
      }
      else  {
        cwsObj.user.courseStatus = "completed";
      }
      //this.saveUserData(cwsObj.user);
    }
  }
  this.getCourseComplete = function() {
    if ((cwsObj.user.courseStatus == "passed") || (cwsObj.user.courseStatus == "completed"))  {
      return true;
    }
    return false;
  }
  this.finished = function()  {
    if (this.initialized) {
      var sessionEnd = new Date();
      var timeInMinutes = ((sessionEnd - sessionStart) / 1000) / 60;
      timeInMinutes = Math.floor(timeInMinutes);
      if (timeInMinutes == 0) {
        timeInMinutes = 1;
      }
      cwsObj.user.sessionTime = cwsObj.user.sessionTime + timeInMinutes;
      this.saveUserData(cwsObj.user);
      if (cwsObj.getCourseCompleted())  {
        this.setCourseComplete();
      }
      currentDataObj.finished();
      this.initialized = false;
    }
    if (!cwsObj.runInNewWindow)  {
      parent.window.close();
    }
    else  {
      if (cwsObj.lcmsReview)  {
        cwsObj.setSessionState(5);
      }
      else  {
        cwsObj.setSessionState(2);
      }
    }
  }

  this.getSessionTime = function() {
    var sessionEnd = new Date();
    var timeInMinutes = ((sessionEnd - sessionStart) / 1000) / 60;
    timeInMinutes = Math.floor(timeInMinutes);
    if (timeInMinutes == 0) {
      timeInMinutes = 1;
    }
    return timeInMinutes;
  }

  this.getTotalTime = function() {
    return this.getSessionTime() + cwsObj.user.sessionTime;
  }

  this.formLogin = function(formObj)  {
    var formUser = new User(cwsObj);
    formUser.userName = formObj.userName.value;
    if (currentDataObj.setUserData(formUser)) {
      if (formUser.password == "")  {
        alert("Your username was not found.\nPlease register.");
        formObj.userName.value = "";
        formObj.password.value = "";
        formObj.userName.focus();
      }
      else  {
        if (formUser.password != CwsUtil.encodePassword(formObj.password.value))  {
          alert("Your password is incorrect.");
          formObj.password.value = "";
          formObj.password.focus();
        }
        else  {
          cwsObj.user = formUser;
          cwsObj.launchKlo(cwsObj.currentKloNum);
        }
      }
    }
    else  {
      cwsObj.setSessionState(3);
    }
  }

  this.formRegister = function(formObj) {
    if (validateRegistrationForm(formObj))  {
      var newUser = new User(cwsObj);
      newUser.password = CwsUtil.encodePassword("karta");
      if (!cwsObj.autoLogin)  {
        newUser.userName = formObj.userName.value;
        newUser.password = CwsUtil.encodePassword(formObj.password.value);
      }
      newUser.firstName = formObj.firstName.value;
      newUser.lastName = formObj.lastName.value;
      cwsObj.setSessionState(0);
      //currentDataObj.saveUserData(newUser);
      cwsObj.user = newUser;
      cwsObj.launchKlo(cwsObj.currentKloNum);
    }
    else  {
      formObj.password.value = "";
      formObj.password2.value = ""
      formObj.password.focus();
    }
  }

  this.saveUserData = function(user) {
    if (this.initialized) {
      if (!currentDataObj.saveUserData(user)) {
        cwsObj.setSessionState(3);
      }
    }
  }

  this.handleFlashData = function(extData) {
    fileDataObj.handleExternalData(extData);
  }

  this.handleExternalData = function(extData) {
    fileDataObj.handleExternalData(extData);
  }

  this.clearData = function() {
    currentDataObj.clearData();
  }

  this.getObjective = function(id)  {
    var objective = cwsObj.user.objectives.getValue(id);
    if (objective == null)  {
      objective = new Objective(id);
      cwsObj.user.objectives.setValue(id,objective);
    }
    return objective;
  }

  this.saveObjectiveData = function(objective,commit) {
    var index = cwsObj.user.objectives.getKeyIndex(objective.id);
    currentDataObj.saveObjectiveData(index,objective,commit);
  }

  this.getInteraction = function(id)  {
    var interaction = cwsObj.user.interactions.getValue(id);
    if (interaction == null)  {
      interaction = new Interaction(id);
      cwsObj.user.interactions.setValue(id,interaction);
    }
    return interaction;
  }

  this.saveInteractionData = function(interaction,commit) {
    var index = cwsObj.user.interactions.getKeyIndex(interaction.id);
    currentDataObj.saveInteractionData(index,interaction,commit);
  }

  this.setScormValue = function(key,value)  {
    if (this.scormActive) {
      currentDataObj.setScormValue(key,value);
    }
  }

  this.getScormValue = function(key)  {
    if (this.scormActive) {
      return currentDataObj.getScormValue(key);
    }
    return "";
  }

  function doAutoLogin()  {
    var autoUser = new User(cwsObj);
    var userDataSet = currentDataObj.setUserData(autoUser);
    if (userDataSet) {
      if ((autoUser.password == "") && (!cwsObj.autoRegister))  {
        cwsObj.contentFrameObj.location.href = cwsObj.rootPath + "data/" + cwsObj.lang + "/register.htm";
      }
      else  {
        if ((autoUser.password != CwsUtil.encodePassword("karta")) && (cwsObj.autoRegister))  {
          autoUser.password = CwsUtil.encodePassword("karta");
          //currentDataObj.saveUserData(autoUser);
        }
        cwsObj.user = autoUser;
        cwsObj.launchKlo(cwsObj.currentKloNum);
      }
    }
    else  {
      cwsObj.setSessionState(3);
    }
  }

  function validateRegistrationForm(formObj)  {
    if (formObj.password.value == formObj.password2.value)  {
      return true;
    }
    else  {
      alert("Your passwords do not match. Please try again.");
      return false;
    }
  }

}

function DataElement()  {
  this.key = "";
  this.value = "";
}
