text: 'use strict';
  /* global KeyEvent */
  define(function(require) {
  var Alarm = require('alarm');
  var ClockView = require('panels/alarm/clock_view');
  var AudioManager = require('audio_manager');
  var FormButton = require('form_button');
  var Sounds = require('sounds');
  var Utils = require('utils');
  var mozL10n = require('l10n');
  var Panel = require('panel');
  var _ = mozL10n.get;
  var html = require('text!panels/alarm_edit/panel.html');
  var constants = require('constants');
  
  var AlarmEdit = function() {
    Panel.apply(this, arguments);
    this.element.innerHTML = html;
  
    mozL10n.translate(this.element);
    var handleDomEvent = this.handleDomEvent.bind(this);
  
    this.element.addEventListener('panel-visibilitychange',
                                  this.handleVisibilityChange.bind(this));
  
    this.selects = {};
    [
      'time', 'repeat', 'sound', 'snooze'
    ].forEach(function(id) {
      this.selects[id] = this.element.querySelector('#' + id + '-select');
    }, this);
  
    this.inputs = {
      name: this.element.querySelector('#alarm-name'),
      volume: this.element.querySelector('#alarm-volume-input')
    };
  
    this.buttons = {};
    [
      'delete', 'close', 'done'
    ].forEach(function(id) {
      this.buttons[id] = this.element.querySelector('#alarm-' + id);
    }, this);
  
    this.checkboxes = {
      vibrate: this.element.querySelector('#vibrate-checkbox')
    };
  
    this.buttons.time = new FormButton(this.selects.time, {
      formatLabel: function(value) {
        var date = new Date();
        // This split(':') is locale-independent per HTML5 <input type=time>
        var splitValue = value.split(':');
        date.setHours(splitValue[0]);
        date.setMinutes(splitValue[1]);
        return Utils.getLocalizedTimeText(date);
      }.bind(this)
    });
    this.buttons.repeat = new FormButton(this.selects.repeat, {
      selectOptions: constants.DAYS,
      id: 'repeat-menu',
      formatLabel: function(daysOfWeek) {
        return this.alarm.summarizeDaysOfWeek(daysOfWeek);
      }.bind(this)
    });
    this.buttons.sound = new FormButton(this.selects.sound, {
      id: 'sound-menu',
      formatLabel: Sounds.formatLabel
    });
    this.buttons.snooze = new FormButton(this.selects.snooze, {
      id: 'snooze-menu',
      formatLabel: function(snooze) {
        return _('nMinutes', {n: snooze});
      }
    });
  
    this.scrollList = this.element.querySelector('#edit-alarm');
    this.sundayListItem = this.element.querySelector('#repeat-select-sunday');
  
    // When the system pops up the ValueSelector, it inadvertently
    // messes with the scrollTop of the current panel. This is a
    // workaround for bug 981255 until the Edit panel becomes a new
    // window per bug 922651.
    this.element.addEventListener('scroll', function() {
      this.element.scrollTop = 0;
    }.bind(this));
  
    mozL10n.translate(this.element);
    // When the language changes, the value of 'weekStartsOnMonday'
    // might change. Since that's more than a simple text string, we
    // can't just use mozL10n.translate().
    mozL10n.ready(this.updateL10n.bind(this));
  
    this.buttons.close.addEventListener('click', handleDomEvent);
    this.buttons.done.addEventListener('click', handleDomEvent);
    this.selects.sound.addEventListener('change', handleDomEvent);
    this.selects.sound.addEventListener('blur', handleDomEvent);
    this.selects.repeat.addEventListener('change', handleDomEvent);
    this.buttons.delete.addEventListener('click', handleDomEvent);
    this.inputs.name.addEventListener('keypress', this.handleNameInput);
    this.inputs.volume.addEventListener('change', handleDomEvent);
  
    // If the phone locks during preview, pause the sound.
    // TODO: When this is no longer a singleton, unbind the listener.
    window.addEventListener('visibilitychange', function() {
      if (document.hidden) {
        this.stopPreviewSound();
      }
    }.bind(this));
  };
  
  AlarmEdit.prototype = Object.create(Panel.prototype);
  
  Utils.extend(AlarmEdit.prototype, {
  
    alarm: null,
    ringtonePlayer: AudioManager.createAudioPlayer(),
  
    handleNameInput: function(evt) {
      // If the user presses enter on the name label, dismiss the
      // keyboard to allow them to continue filling out the other
      // fields. This is not in the `handleEvent` function because we
      // only want to call `.preventDefault` sometimes.
      if (evt.keyCode === KeyEvent.DOM_VK_RETURN) {
        evt.preventDefault();
        evt.target.blur();
      }
    },
  
    updateL10n: function() {
      // Move the weekdays around to properly account for whether the
      // week starts on Sunday or Monday.
      var weekStartsOnMonday = parseInt(_('weekStartsOnMonday'), 10);
      var parent = this.sundayListItem.parentElement;
      if (weekStartsOnMonday) {
        // Sunday gets moved to the end.
        parent.appendChild(this.sundayListItem);
      } else {
        // Sunday goes first.
        parent.insertBefore(this.sundayListItem, parent.firstChild);
      }
    },
  
    // The name `handleEvent` is already defined by the Panel class, so this
    // method must be named uniquely to avoid overriding that functionality.
    handleDomEvent: function aev_handleDomEvent(evt) {
      evt.preventDefault();
      var input = evt.target;
      if (!input) {
        return;
      }
  
      switch (input) {
        case this.buttons.close:
          ClockView.show();
          break;
        case this.buttons.done:
          ClockView.show();
          this.save();
          break;
        case this.selects.sound:
          switch (evt.type) {
            case 'change':
              this.previewSound();
              break;
            case 'blur':
              this.stopPreviewSound();
              break;
          }
          break;
        case this.buttons.delete:
          ClockView.show();
          this.delete();
          break;
        case this.selects.repeat:
          this.alarm.repeat = this.buttons.repeat.value;
          break;
        case this.inputs.volume:
          // Alarm Volume is applied to all alarms.
          AudioManager.setAlarmVolume(this.getAlarmVolumeValue());
          break;
      }
    },
  
    focusMenu: function aev_focusMenu(menu) {
      setTimeout(function() { menu.focus(); }, 10);
    },
  
    handleVisibilityChange: function aev_show(evt) {
      var isVisible = evt.detail.isVisible;
      var alarm;
      if (!isVisible) {
        return;
      }
      // `navData` is set by the App module in `navigate`.
      alarm = this.navData;
      // scroll to top of form list
      this.scrollList.scrollTop = 0;
  
      this.element.classList.toggle('new', !alarm);
      this.alarm = new Alarm(alarm); // alarm may be null
  
      // Set to empty string if the Alarm doesn't have an ID,
      // otherwise dataset will automatically stringify it
      // to be "undefined" rather than "".
      this.element.dataset.id = this.alarm.id || '';
      this.inputs.name.value = this.alarm.label;
      this.inputs.volume.value = AudioManager.getAlarmVolume();
  
      // Init time, repeat, sound, snooze selection menu.
      this.initTimeSelect();
      this.initRepeatSelect();
      this.initSoundSelect();
      this.initSnoozeSelect();
      this.checkboxes.vibrate.checked = this.alarm.vibrate;
  
      // Update the labels for any FormButton dropdowns that have
      // changed, because setting <select>.value does not fire a change
      // event.
      for (var key in this.buttons) {
        var button = this.buttons[key];
        if (button instanceof FormButton) {
          button.refresh();
        }
      }
  
      location.hash = '#alarm-edit-panel';
  
      // We're appending new elements to DOM so to make sure headers are
      // properly resized and centered, we emmit a lazyload event.
      // This will be removed when the gaia-header web component lands.
      window.dispatchEvent(new CustomEvent('lazyload', {
        detail: this.element
      }));
    },
  
    initTimeSelect: function aev_initTimeSelect() {
      // HTML5 <input type=time> expects 24-hour HH:MM format.
      var hour = parseInt(this.alarm.hour, 10);
      var minute = parseInt(this.alarm.minute, 10);
      this.selects.time.value = (hour < 10 ? '0' : '') + hour +
        ':' + (minute < 10 ? '0' : '') + minute;
    },
  
    getTimeSelect: function aev_getTimeSelect() {
      // HTML5 <input type=time> returns data in 24-hour HH:MM format.
      var splitTime = this.selects.time.value.split(':');
      return { hour: splitTime[0], minute: splitTime[1] };
    },
  
    initRepeatSelect: function aev_initRepeatSelect() {
      this.buttons.repeat.value = this.alarm.repeat;
    },
  
    initSoundSelect: function aev_initSoundSelect() {
      this.buttons.sound.value = this.alarm.sound;
    },
  
    getSoundSelect: function aev_getSoundSelect() {
      return this.buttons.sound.value;
    },
  
    previewSound: function aev_previewSound() {
      var ringtoneName = this.getSoundSelect();
      this.ringtonePlayer.playRingtone(ringtoneName);
    },
  
    stopPreviewSound: function aev_stopPreviewSound() {
      this.ringtonePlayer.pause();
    },
  
    initSnoozeSelect: function aev_initSnoozeSelect() {
      this.buttons.snooze.value = this.alarm.snooze;
    },
  
    getSnoozeSelect: function aev_getSnoozeSelect() {
      return this.buttons.snooze.value;
    },
  
    getRepeatSelect: function aev_getRepeatSelect() {
      return this.buttons.repeat.value;
    },
  
    getAlarmVolumeValue: function() {
      return parseFloat(this.inputs.volume.value);
    },
  
    save: function aev_save(callback) {
      if (this.element.dataset.id && this.element.dataset.id !== '') {
        this.alarm.id = parseInt(this.element.dataset.id, 10);
      } else {
        delete this.alarm.id;
      }
  
      this.alarm.label = this.inputs.name.value;
  
      var time = this.getTimeSelect();
      this.alarm.time = [time.hour, time.minute];
      this.alarm.repeat = this.buttons.repeat.value;
      this.alarm.sound = this.getSoundSelect();
      this.alarm.vibrate = this.checkboxes.vibrate.checked;
      this.alarm.snooze = parseInt(this.getSnoozeSelect(), 10);
      AudioManager.setAlarmVolume(this.getAlarmVolumeValue());
  
      this.alarm.cancel();
  
      this.alarm.setEnabled(true, function(err, alarm) {
        if (err) {
          callback && callback(err, alarm);
          return;
        }
        window.dispatchEvent(new CustomEvent('alarm-changed', {
          detail: { alarm: alarm, showBanner: true }
        }));
        callback && callback(null, alarm);
      });
    },
  
    delete: function aev_delete(callback) {
      if (!this.alarm.id) {
        setTimeout(callback.bind(null, new Error('no alarm id')), 0);
        return;
      }
  
      this.alarm.delete(callback);
    }
  
  });
  
  return AlarmEdit;
  });
  