public void info() {

    World world = null;

    if (this.args.length == 1 && this.sender instanceof Player) {
      world = ((Player) this.sender).getLocation().getWorld();
    } else if (this.args.length > 1) {
      world = Bukkit.getWorld(this.args[1]);

      if (world == null) {
        message("World <" + this.args[1] + "> does not exist");
        return;
      }
    } else return;

    Map map = this.editor.getMap(world);

    if (map == null) {
      message("World <" + world.getName() + "> is not oppened in editor");
      return;
    }

    // Informations sur la map
    message(ChatColor.DARK_AQUA + "Map <" + map.getWorldName() + ">");
    message("Object count : " + map.getSigns().size());
    message(
        "Available objects ("
            + ObjectType.getObjectTypeNames().size()
            + ") : "
            + ObjectType.getObjectTypeNames());
  }
  public void signSet(Sign sign, Map map) {
    if (this.args.length < 4) return;

    String key = this.args[2];
    String value = Utils.multiArgs(this.args, 3);

    if (!sign.getDefaultOptions().containsKey(key)
        && !sign.getObjectType().equals(ObjectType.CUSTOM)) {
      message("Option <" + key + "> is not defined for object " + sign.getTypeName());
      return;
    }

    // Option value reset
    if (value.equals("default") && sign.getOptions().containsKey(key)) {
      sign.getOptions().remove(key);
      message(
          "Option <"
              + key
              + "> has now it default value "
              + ChatColor.WHITE
              + sign.getDefaultOptions().get(key).getValue());
    } else {
      sign.getOptions().put(key, value);
      message("Option <" + key + "> has now value " + ChatColor.WHITE + value);
    }

    try {
      map.writeSigns();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  public void signOutput(Sign sign, Map map) {
    if (this.args.length <= 4) return;
    int flux;
    if (this.args[3].equalsIgnoreCase("n")) {
      flux = map.getNewSignal();
    } else if (!Utils.isInt(this.args[3])) return;
    else {
      flux = Integer.parseInt(this.args[3]);
    }
    boolean fluxValue;
    if (this.args[4].equalsIgnoreCase("true")
        || this.args[4].equalsIgnoreCase("t")
        || this.args[4].equalsIgnoreCase("on")) fluxValue = true;
    else if (this.args[4].equalsIgnoreCase("false")
        || this.args[4].equalsIgnoreCase("f")
        || this.args[4].equalsIgnoreCase("off")) fluxValue = false;
    else return;

    switch (this.args[2]) {
      case "add":
      case "a":
      case "+":
        this.signAddOutput(sign, map, flux, fluxValue);
        break;
      case "remove":
      case "r":
      case "-":
        this.signRemoveOutput(sign, map, flux, fluxValue);
        break;
    }
  }
  public void signRemoveInput(Sign sign, Map map, int flux) {

    ArrayList<Integer> newInputs = new ArrayList<Integer>();

    Iterator<Integer> it = sign.getInputsSignals().iterator();

    while (it.hasNext()) {
      int i = it.next();
      if (i == flux) continue;
      else newInputs.add(i);
    }

    sign.setInputsSignals(newInputs);

    this.editor.buildSign(sign, map);

    try {
      map.writeSigns();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    this.signInfo(sign, map);
  }
  public void signInfo(Sign sign, Map map) {
    int number = map.getSignNumber(sign);
    message("*******************************");
    message(ChatColor.WHITE + "" + ChatColor.BOLD + sign.getTypeName() + " #" + number);
    message("*******************************");

    message("Inputs : " + this.editor.displayInputs(sign));
    message("Outputs ON : " + this.editor.displayOutputs(sign, true));
    message("Outputs OFF : " + this.editor.displayOutputs(sign, false));

    message(ChatColor.YELLOW + "" + ChatColor.BOLD + "Options :");

    for (String key : sign.getOptions().keySet()) {
      message(ChatColor.WHITE + key + " : " + ChatColor.GRAY + sign.getOptions().get(key));
    }

    for (String key : sign.getDefaultOptions().keySet()) {
      if (sign.getOptions().containsKey(key)) continue;
      message(
          ChatColor.GRAY
              + ""
              + ChatColor.ITALIC
              + key
              + " : "
              + ChatColor.GRAY
              + sign.getDefaultOptions().get(key).getValue()
              + " ("
              + sign.getDefaultOptions().get(key).getOptionType().name().toLowerCase()
              + ")");
    }
  }
  public void go() {
    if (!(this.sender instanceof Player)) return;

    Player p = (Player) this.sender;
    Map map = this.editor.getMap(p.getWorld());
    if (map == null) return;
    if (this.args.length == 1) return;
    if (!Utils.isInt(this.args[1])) return;
    int n = Integer.parseInt(this.args[1]);
    if (n < 1) return;
    Sign sign = map.getSign(n);

    if (sign == null) {
      message("Sign not found, check /editor find...");
      return;
    }

    p.teleport(sign.getRealLocation(p.getWorld()));
    message("Teleported to sign #" + n);
  }
  public void signAddOutput(Sign sign, Map map, int flux, boolean fluxValue) {
    sign.getOutputSignals().add(new OutputSignal(flux, fluxValue));
    this.editor.buildSign(sign, map);

    try {
      map.writeSigns();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    this.signInfo(sign, map);
  }
  public void signAddInput(Sign sign, Map map, int flux) {
    sign.getInputsSignals().add(flux);
    this.editor.buildSign(sign, map);

    try {
      map.writeSigns();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    this.signInfo(sign, map);
  }
  public void find() {
    if (!(this.sender instanceof Player)) return;

    Player p = (Player) this.sender;
    Map map = this.editor.getMap(p.getWorld());
    if (map == null) return;

    ArrayList<Sign> results;

    if (this.args.length == 1) {
      message("Searching for signs...");
      results = map.getSigns();
    } else {
      results = new ArrayList<Sign>();
      for (Sign s : map.getSigns()) {
        if (s.getObjectName().contains(this.args[1])) {
          results.add(s);
        }
      }
    }

    message(results.size() + " signs found :");

    for (Sign sign : results) {

      int n = map.getSignNumber(sign);
      int distance = (int) Math.round(sign.getRealLocation(p.getWorld()).distance(p.getLocation()));
      message(
          "#"
              + n
              + " "
              + ChatColor.WHITE
              + sign.getTypeName()
              + ChatColor.GRAY
              + " ("
              + distance
              + "m)");
    }
  }
  public void signPaste(Sign sign, Map map) {
    if (!this.editor.getClipBoards().containsKey((Player) sender)) {
      message("Use /editor sign copy first !");
      return;
    }

    Sign source = this.editor.getClipBoards().get((Player) sender);
    sign.copyData(source);
    this.editor.buildSign(sign, map);

    try {
      map.writeSigns();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    message(ChatColor.YELLOW + "Sign " + sign.getTypeName() + " pasted");
  }
  public void signRemoveOutput(Sign sign, Map map, int flux, boolean fluxValue) {
    ArrayList<OutputSignal> newOutputs = new ArrayList<OutputSignal>();

    for (OutputSignal os : sign.getOutputSignals()) {
      if (os.getSignal() == flux && os.isOn() == fluxValue) continue;
      newOutputs.add(os);
    }

    sign.setOutputSignals(newOutputs);

    this.editor.buildSign(sign, map);

    try {
      map.writeSigns();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    this.signInfo(sign, map);
  }
  public void signInput(Sign sign, Map map) {
    if (this.args.length <= 3) return;

    int flux;
    if (this.args[3].equalsIgnoreCase("n")) {
      flux = map.getNewSignal();
    } else if (!Utils.isInt(this.args[3])) return;
    else {
      flux = Integer.parseInt(this.args[3]);
    }

    switch (this.args[2]) {
      case "add":
      case "a":
      case "+":
        this.signAddInput(sign, map, flux);
        break;
      case "remove":
      case "r":
      case "-":
        this.signRemoveInput(sign, map, flux);
        break;
    }
  }