text: /*
   * Copyright 2012, Mozilla Foundation and contributors
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  'use strict';
  
  var assert = require('../testharness/assert');
  var helpers = require('./helpers');
  var Commands = require('../commands/commands').Commands;
  
  var startCount;
  var events;
  
  var commandsChange = function(ev) {
    events++;
  };
  
  exports.setup = function(options) {
    startCount = options.requisition.system.commands.getAll().length;
    events = 0;
  };
  
  exports.shutdown = function(options) {
    startCount = undefined;
    events = undefined;
  };
  
  exports.testAddRemove1 = function(options) {
    var commands = options.requisition.system.commands;
  
    return helpers.audit(options, [
      {
        name: 'testadd add',
        setup: function() {
          commands.onCommandsChange.add(commandsChange);
  
          commands.add({
            name: 'testadd',
            exec: function() {
              return 1;
            }
          });
  
          assert.is(commands.getAll().length,
                    startCount + 1,
                    'add command success');
          assert.is(events, 1, 'add event');
  
          return helpers.setInput(options, 'testadd');
        },
        check: {
          input:  'testadd',
          hints:         '',
          markup: 'VVVVVVV',
          cursor: 7,
          current: '__command',
          status: 'VALID',
          predictions: [ ],
          unassigned: [ ],
          args: { }
        },
        exec: {
          output: /^1$/
        }
      },
      {
        name: 'testadd alter',
        setup: function() {
          commands.add({
            name: 'testadd',
            exec: function() {
              return 2;
            }
          });
  
          assert.is(commands.getAll().length,
                    startCount + 1,
                    'read command success');
          assert.is(events, 2, 'read event');
  
          return helpers.setInput(options, 'testadd');
        },
        check: {
          input:  'testadd',
          hints:         '',
          markup: 'VVVVVVV',
        },
        exec: {
          output: '2'
        }
      },
      {
        name: 'testadd remove',
        setup: function() {
          commands.remove('testadd');
  
          assert.is(commands.getAll().length,
                    startCount,
                    'remove command success');
          assert.is(events, 3, 'remove event');
  
          return helpers.setInput(options, 'testadd');
        },
        check: {
          typed: 'testadd',
          cursor: 7,
          current: '__command',
          status: 'ERROR',
          unassigned: [ ],
        }
      }
    ]);
  };
  
  exports.testAddRemove2 = function(options) {
    var commands = options.requisition.system.commands;
  
    commands.add({
      name: 'testadd',
      exec: function() {
        return 3;
      }
    });
  
    assert.is(commands.getAll().length,
              startCount + 1,
              'rereadd command success');
    assert.is(events, 4, 'rereadd event');
  
    return helpers.audit(options, [
      {
        setup: 'testadd',
        exec: {
          output: /^3$/
        },
        post: function() {
          commands.remove({
            name: 'testadd'
          });
  
          assert.is(commands.getAll().length,
                    startCount,
                    'reremove command success');
          assert.is(events, 5, 'reremove event');
        }
      },
      {
        setup: 'testadd',
        check: {
          typed: 'testadd',
          status: 'ERROR'
        }
      }
    ]);
  };
  
  exports.testAddRemove3 = function(options) {
    var commands = options.requisition.system.commands;
  
    commands.remove({ name: 'nonexistant' });
    assert.is(commands.getAll().length,
              startCount,
              'nonexistant1 command success');
    assert.is(events, 5, 'nonexistant1 event');
  
    commands.remove('nonexistant');
    assert.is(commands.getAll().length,
              startCount,
              'nonexistant2 command success');
    assert.is(events, 5, 'nonexistant2 event');
  
    commands.onCommandsChange.remove(commandsChange);
  };
  
  exports.testAltCommands = function(options) {
    var commands = options.requisition.system.commands;
    var altCommands = new Commands(options.requisition.system.types);
  
    var tss = {
      name: 'tss',
      params: [
        { name: 'str', type: 'string' },
        { name: 'num', type: 'number' },
        { name: 'opt', type: { name: 'selection', data: [ '1', '2', '3' ] } },
      ],
      customProp1: 'localValue',
      customProp2: true,
      customProp3: 42,
      exec: function(args, context) {
        return context.commandName + ':' +
                args.str + ':' + args.num + ':' + args.opt;
      }
    };
    altCommands.add(tss);
  
    var commandSpecs = altCommands.getCommandSpecs();
    assert.is(JSON.stringify(commandSpecs),
              '[{"item":"command","name":"tss","params":[' +
                '{"name":"str","type":"string"},' +
                '{"name":"num","type":"number"},' +
                '{"name":"opt","type":{"name":"selection","data":["1","2","3"]}}' +
              '],"isParent":false}]',
              'JSON.stringify(commandSpecs)');
  
    var customProps = [ 'customProp1', 'customProp2', 'customProp3', ];
    var commandSpecs2 = altCommands.getCommandSpecs(customProps);
    assert.is(JSON.stringify(commandSpecs2),
              '[{' +
                '"item":"command",' +
                '"name":"tss",' +
                '"params":[' +
                  '{"name":"str","type":"string"},' +
                  '{"name":"num","type":"number"},' +
                  '{"name":"opt","type":{"name":"selection","data":["1","2","3"]}}' +
                '],' +
                '"isParent":false,' +
                '"customProp1":"localValue",' +
                '"customProp2":true,' +
                '"customProp3":42' +
              '}]',
              'JSON.stringify(commandSpecs)');
  
    var remoter = function(args, context) {
      assert.is(context.commandName, 'tss', 'commandName is tss');
  
      var cmd = altCommands.get(context.commandName);
      return cmd.exec(args, context);
    };
  
    commands.addProxyCommands(commandSpecs, remoter, 'proxy', 'test');
  
    var parent = commands.get('proxy');
    assert.is(parent.name, 'proxy', 'Parent command called proxy');
  
    var child = commands.get('proxy tss');
    assert.is(child.name, 'proxy tss', 'child command called proxy tss');
  
    return helpers.audit(options, [
      {
        setup:    'proxy tss foo 6 3',
        check: {
          input:  'proxy tss foo 6 3',
          hints:                    '',
          markup: 'VVVVVVVVVVVVVVVVV',
          cursor: 17,
          status: 'VALID',
          args: {
            str: { value: 'foo', status: 'VALID' },
            num: { value: 6, status: 'VALID' },
            opt: { value: '3', status: 'VALID' }
          }
        },
        exec: {
          output: 'tss:foo:6:3'
        },
        post: function() {
          commands.remove('proxy');
          commands.remove('proxy tss');
  
          assert.is(commands.get('proxy'), undefined, 'remove proxy');
          assert.is(commands.get('proxy tss'), undefined, 'remove proxy tss');
        }
      }
    ]);
  };
  