/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const {classes: Cc, interfaces: Ci, utils: Cu} = Components;

Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Services.jsm");

const reporter = Cc["@mozilla.org/datareporting/service;1"]
                   .getService(Ci.nsISupports)
                   .wrappedJSObject
                   .healthReporter;

const policy = Cc["@mozilla.org/datareporting/service;1"]
                 .getService(Ci.nsISupports)
                 .wrappedJSObject
                 .policy;

const prefs = new Preferences("datareporting.healthreport.");


let healthReportWrapper = {
  init: function () {
    reporter.onInit().then(healthReportWrapper.refreshPayload,
                           healthReportWrapper.handleInitFailure);

    let iframe = document.getElementById("remote-report");
    iframe.addEventListener("load", healthReportWrapper.initRemotePage, false);
    let report = this._getReportURI();
    iframe.src = report.spec;
    prefs.observe("uploadEnabled", this.updatePrefState, healthReportWrapper);
  },

  uninit: function () {
    prefs.ignore("uploadEnabled", this.updatePrefState, healthReportWrapper);
  },

  _getReportURI: function () {
    let url = Services.urlFormatter.formatURLPref("datareporting.healthreport.about.reportUrl");
    return Services.io.newURI(url, null, null);
  },

  onOptIn: function () {
    policy.recordHealthReportUploadEnabled(true,
                                           "Health report page sent opt-in command.");
    this.updatePrefState();
  },

  onOptOut: function () {
    policy.recordHealthReportUploadEnabled(false,
                                           "Health report page sent opt-out command.");
    this.updatePrefState();
  },

  updatePrefState: function () {
    try {
      let prefs = {
        enabled: policy.healthReportUploadEnabled,
      }
      this.injectData("prefs", prefs);
    } catch (e) {
      this.reportFailure(this.ERROR_PREFS_FAILED);
    }
  },

  refreshPayload: function () {
    reporter.collectAndObtainJSONPayload().then(healthReportWrapper.updatePayload, 
                                                healthReportWrapper.handlePayloadFailure);
  },

  updatePayload: function (data) {
    healthReportWrapper.injectData("payload", data);
  },

  injectData: function (type, content) {
    let report = this._getReportURI();
    
    // file URIs can't be used for targetOrigin, so we use "*" for this special case
    // in all other cases, pass in the URL to the report so we properly restrict the message dispatch
    let reportUrl = report.scheme == "file" ? "*" : report.spec;

    let data = {
      type: type,
      content: content
    }

    let iframe = document.getElementById("remote-report");
    iframe.contentWindow.postMessage(data, reportUrl);
  },

  handleRemoteCommand: function (evt) {
    switch (evt.detail.command) {
      case "DisableDataSubmission":
        this.onOptOut();
        break;
      case "EnableDataSubmission":
        this.onOptIn();
        break;
      case "RequestCurrentPrefs":
        this.updatePrefState();
        break;
      case "RequestCurrentPayload":
        this.refreshPayload();
        break;
      default:
        Cu.reportError("Unexpected remote command received: " + evt.detail.command + ". Ignoring command.");
        break;
    }
  },

  initRemotePage: function () {
    let iframe = document.getElementById("remote-report").contentDocument;
    iframe.addEventListener("RemoteHealthReportCommand",
                            function onCommand(e) {healthReportWrapper.handleRemoteCommand(e);},
                            false);
    healthReportWrapper.updatePrefState();
  },

  // error handling
  ERROR_INIT_FAILED:    1,
  ERROR_PAYLOAD_FAILED: 2,
  ERROR_PREFS_FAILED:   3,

  reportFailure: function (error) {
    let details = {
      errorType: error,
    }
    healthReportWrapper.injectData("error", details);
  },

  handleInitFailure: function () {
    healthReportWrapper.reportFailure(healthReportWrapper.ERROR_INIT_FAILED);
  },

  handlePayloadFailure: function () {
    healthReportWrapper.reportFailure(healthReportWrapper.ERROR_PAYLOAD_FAILED);
  },
}
