/*
   * (non-Javadoc)
   *
   * @see org.bigwiv.blastgraph.command.Command#concreteExecute()
   */
  @Override
  public void concreteExecute() {
    String curPath = Global.getAppPath(this.getClass());
    File mclGraphFile = new File(curPath + File.separator + "mcl_graph_file");
    File mclClustFile =
        new File(
            curPath
                + File.separator
                + "out.mcl_graph_file.I"
                + ("" + inflation).replace(".", "").substring(0, 2));
    // System.out.println(mclClustFile);
    try {
      ArrayList<ValueEdge> edges = new ArrayList<ValueEdge>(Global.graph.getEdges());

      BufferedWriter bw;

      bw = new BufferedWriter(new FileWriter(mclGraphFile));

      Global.WORK_STATUS.setMessage("");
      Global.WORK_STATUS.setMessage("Stage1: Generating Tabular Format...");

      for (ValueEdge valueEdge : edges) {
        Pair<HitVertex> pair = Global.graph.getEndpoints(valueEdge);
        HitVertex hv1 = pair.getFirst();
        HitVertex hv2 = pair.getSecond();

        double weight = 0;

        if (weightType == EVALUE_WEIGHT) {

          double evalue = valueEdge.getExpectValue();

          if (evalue >= lowCutoff) {
            weight = 0;
          } else if (evalue < highCutoff) {
            weight = -Math.log10(highCutoff);
          } else {
            weight = -Math.log10(evalue);
          }

        } else if (weightType == SCORE_WEIGHT) {
          double score = valueEdge.getScore();
          if (score <= lowCutoff) {
            weight = 0;
          } else if (score > highCutoff) {
            weight = highCutoff;
          } else {
            weight = score;
          }
        } else if (weightType == SCORE_DENSITY_WEIGHT) {
          double scoreDensity = Global.graph.getScoreDensity(valueEdge);
          if (scoreDensity <= lowCutoff) {
            weight = 0;
          } else if (scoreDensity > highCutoff) {
            weight = highCutoff;
          } else {
            weight = scoreDensity;
          }
        }

        bw.write(hv1.getId() + "\t" + hv2.getId() + "\t" + weight + "\n");
      }

      // store single vertices
      for (HitVertex hv : Global.graph.getVertices()) {
        if (Global.graph.getInEdges(hv).size() == 0)
          bw.write(hv.getId() + "\t" + hv.getId() + "\t" + 10 + "\n");
      }

      bw.close();
      Global.WORK_STATUS.setMessage("Stage1 Complete");
      Global.WORK_STATUS.setMessage("");

      String mclCmd;
      String cmdPath = Global.SETTING.get("MCL_PATH");
      if (cmdPath != null && (new File(cmdPath).isDirectory())) {
        mclCmd = cmdPath + File.separator + "mcl";
      } else {
        mclCmd = "mcl";
      }

      ProcessBuilder pb =
          new ProcessBuilder(mclCmd, "mcl_graph_file", "--abc", "-I", "" + inflation);
      // System.out.println(pb.command().toString());
      pb.redirectErrorStream(true);
      pb.directory(new File(curPath));
      Process p = pb.start();
      Global.WORK_STATUS.setMessage("Stage2: Markov Clustering...");
      BufferedInputStream in = new BufferedInputStream(p.getInputStream());
      BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
      String lineStr;

      while ((lineStr = inBr.readLine()) != null) {
        // System.out.println(lineStr);
        Global.WORK_STATUS.setMessage(lineStr);
      }

      if (p.waitFor() != 0) {
        if (p.exitValue() == 1)
          // System.err.println("Failed to run mcl!");
          Global.WORK_STATUS.setError("Failed to run mcl!");
      }

      inBr.close();
      in.close();
      Global.WORK_STATUS.setMessage("Stage2 Complete");

      mclGraphFile.delete();

      Global.WORK_STATUS.setMessage("");

      Global.WORK_STATUS.setMessage("Stage3: Regenerating SubGraphs...");
      BufferedReader br = new BufferedReader(new FileReader(mclClustFile));
      String line = br.readLine();

      BlastGraph<HitVertex, ValueEdge> tempGraph = new BlastGraph<HitVertex, ValueEdge>();
      int count = 0;
      while (line != null && !line.equals("")) {
        String[] ids = line.split("\t");
        // set to store vertices
        Set<HitVertex> hvs2 = new HashSet<HitVertex>();

        // get and add vertices into hvs by GI in ids
        for (int i = 0; i < ids.length; i++) {
          hvs2.add(Global.graph.getVertex(ids[i]));
        }

        tempGraph.union(FilterUtils.createInducedSubgraph(hvs2, Global.graph));

        line = br.readLine();
        Global.WORK_STATUS.setMessage("Subgraph: " + (++count));
      }

      br.close();

      mclClustFile.delete();

      Global.graph.copy(tempGraph);

      Global.WORK_STATUS.setMessage("Stage3 Complete");
      Global.WORK_STATUS.setMessage("");
      Global.WORK_STATUS.setMessage("Markov Clustering Complete");
      // System.out.println(curPath);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  @Override
  public void actionPerformed(ActionEvent e) {
    int index = valueComboBox.getSelectedIndex();
    int index2 = methodComboBox.getSelectedIndex();

    if (!plot2dPanel.getPlots().isEmpty()) {
      plot2dPanel.getPlots().clear();
    }

    // System.out.println("changed: " + index + " " + index2);
    Vector vector = new Vector();
    if (index == 0) {
      Collection<HitVertex> hvs = graph.getVertices();
      for (HitVertex hitVertex : hvs) {
        vector.add((double) hitVertex.getLength());
      }
    } else if (index == 1) {
      Collection<ValueEdge> ves = graph.getEdges();
      for (ValueEdge ve : ves) {
        if (ve.getExpectValue() == 0) {
          vector.add(-200.0);
        } else {
          vector.add(Math.log10(ve.getExpectValue()));
        }
      }
    } else if (index == 2) {
      Collection<ValueEdge> ves = graph.getEdges();
      for (ValueEdge ve : ves) {
        vector.add(graph.getCoverage(ve));
      }
    } else if (index == 3) {
      Collection<ValueEdge> ves = graph.getEdges();
      for (ValueEdge ve : ves) {
        vector.add(graph.getCoverage2(ve));
      }
    } else if (index == 4) {
      Collection<ValueEdge> ves = graph.getEdges();
      for (ValueEdge ve : ves) {
        vector.add(graph.getScoreDensity(ve));
      }
    } else if (index == 5) {
      Collection<ValueEdge> ves = graph.getEdges();
      for (ValueEdge ve : ves) {
        vector.add(graph.getPercentageIdentity(ve));
      }
    } else if (index == 6) {
      Collection<ValueEdge> ves = graph.getEdges();
      for (ValueEdge ve : ves) {
        vector.add(graph.getPercentagePositive(ve));
      }
    } else if (index == 7) {
      final BlastGraph<HitVertex, ValueEdge> tmpGraph = new BlastGraph<HitVertex, ValueEdge>();
      tmpGraph.copy(graph);
      ArrayList<ValueEdge> ves = new ArrayList<ValueEdge>(tmpGraph.getEdges());
      vertexCount = new double[ves.size()];
      values = new double[ves.size()];
      Collections.sort(
          ves,
          new Comparator<ValueEdge>() {
            @Override
            public int compare(ValueEdge arg0, ValueEdge arg1) {
              // from biggest to smallest
              if (arg0.getExpectValue() < arg1.getExpectValue()) {
                return 1;
              } else if (arg0.getExpectValue() > arg1.getExpectValue()) {
                return -1;
              } else {
                return 0;
              }
            }
          });

      for (int i = 0; i < ves.size(); i++) {
        ValueEdge ve = ves.get(i);
        if (ve.getExpectValue() == 0) {
          values[i] = -200.0;
        } else {
          values[i] = Math.log10(ve.getExpectValue());
        }
        // values[i] = ve.getExpectValue();
        tmpGraph.removeEdge(ve);
        tmpGraph.generateSubSet();
        vertexCount[i] = tmpGraph.getSubSet().get(0).size();
        // System.out.println(values[i] + ": " + vertexCount[i]);
      }

    } else if (index == 8) {
      final BlastGraph<HitVertex, ValueEdge> tmpGraph = new BlastGraph<HitVertex, ValueEdge>();
      tmpGraph.copy(graph);
      ArrayList<ValueEdge> ves = new ArrayList<ValueEdge>(tmpGraph.getEdges());
      vertexCount = new double[ves.size()];
      values = new double[ves.size()];
      Collections.sort(
          ves,
          new Comparator<ValueEdge>() {
            @Override
            public int compare(ValueEdge arg0, ValueEdge arg1) {
              // from smallest to biggest
              if (tmpGraph.getCoverage(arg0) > tmpGraph.getCoverage(arg1)) {
                return 1;
              } else if (tmpGraph.getCoverage(arg0) < tmpGraph.getCoverage(arg1)) {
                return -1;
              } else {
                return 0;
              }
            }
          });

      for (int i = 0; i < ves.size(); i++) {
        ValueEdge ve = ves.get(i);
        values[i] = tmpGraph.getCoverage(ve);
        tmpGraph.removeEdge(ve);
        tmpGraph.generateSubSet();
        vertexCount[i] = tmpGraph.getSubSet().get(0).size();
        // System.out.println(values[i] + ": " + vertexCount[i]);
      }
    } else {
      final BlastGraph<HitVertex, ValueEdge> tmpGraph = new BlastGraph<HitVertex, ValueEdge>();
      tmpGraph.copy(graph);
      ArrayList<ValueEdge> ves = new ArrayList<ValueEdge>(tmpGraph.getEdges());
      vertexCount = new double[ves.size()];
      values = new double[ves.size()];
      Collections.sort(
          ves,
          new Comparator<ValueEdge>() {
            @Override
            public int compare(ValueEdge arg0, ValueEdge arg1) {
              // from smallest to biggest
              if (tmpGraph.getCoverage2(arg0) > tmpGraph.getCoverage2(arg1)) {
                return 1;
              } else if (tmpGraph.getCoverage2(arg0) < tmpGraph.getCoverage2(arg1)) {
                return -1;
              } else {
                return 0;
              }
            }
          });

      for (int i = 0; i < ves.size(); i++) {
        ValueEdge ve = ves.get(i);
        values[i] = tmpGraph.getCoverage2(ve);
        tmpGraph.removeEdge(ve);
        tmpGraph.generateSubSet();
        vertexCount[i] = tmpGraph.getSubSet().get(0).size();
        // System.out.println(values[i] + ": " + vertexCount[i]);
      }
    }

    double[] array = new double[vector.size()];
    for (int i = 0; i < vector.size(); i++) {
      array[i] = (Double) vector.get(i);
    }

    Arrays.sort(array);
    double[] arrayIndex = new double[array.length];
    for (int i = 0; i < arrayIndex.length; i++) {
      arrayIndex[i] = i + 1;
    }

    // System.out.println(array[1]);
    if (index2 == 0) {
      // if (valueComboBox.getItemCount() == items.length) {
      // addAdditional();
      // }
      if (index < items.length) {
        plot2dPanel.addLinePlot("Array", array, arrayIndex);
      } else {
        // System.out.println(values.length + " " + vertexCount.length);
        plot2dPanel.addLinePlot("vertexCount", values, vertexCount);
      }
      plot2dPanel.repaint();
    } else if (index2 == 1) {
      // try {
      // Image image = bsTool.getHistogram(array);
      // statisticsPanel.setImage(image);
      // statisticsPanel.repaint();
      // this.pack();
      // } catch (IOException e) {
      // e.printStackTrace();
      // }
      // if (valueComboBox.getItemCount() > items.length) {
      // removeAdditional();
      // }
      plot2dPanel.addHistogramPlot("Array", array, 20);
      plot2dPanel.repaint();
    }
  }