// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
package graphtea.extensions.reports.topological;

import java.util.List;
import graphtea.extensions.AlgorithmUtils;
import graphtea.graph.graph.Edge;
import graphtea.graph.graph.GraphModel;
import graphtea.graph.graph.RenderTable;
import graphtea.platform.lang.CommandAttitude;
import graphtea.plugins.reports.extension.GraphReportExtension;

import java.util.ArrayList;
import java.util.Collections;

/**
 * @author Ali Rostami 

 */

@CommandAttitude(name = "m3finalconj", abbreviation = "_m3conj")
public class EM1UpperBound implements GraphReportExtension<RenderTable> {
    public String getName() {
        return "EM1 Upper";
    }

    public String getDescription() {
        return "EM1 Upper";
    }

    public RenderTable calculate(GraphModel g) {
        ZagrebIndexFunctions zif = new ZagrebIndexFunctions(g);
        ZagrebIndexFunctions zifL = new ZagrebIndexFunctions(
                AlgorithmUtils.createLineGraph(g)
        );

        RenderTable ret = new RenderTable();

        List<String> titles = new ArrayList<>();
       //  titles.add(" M^3_1(G) ");
      //  titles.add("Psi1 ");
     //   titles.add("Psi2");
    //    titles.add("Zhou");
   //     titles.add("N4");
  //      titles.add("N2");
 //       titles.add("N1");
//        titles.add("Theorem 1");
       //   titles.add("3R.H.S");
        //  titles.add("2R.H.S");
        //  titles.add("1L.H.S");
          titles.add("EF");
          titles.add("R.H.S");
        //  titles.add("2R.H.S");
        //  titles.add("3R.H.S");
        
        ret.setTitles(titles);
        double m = g.getEdgesCount();

        double maxEdge = 0;
        double maxEdge2 = 0;

        ArrayList<Integer> all = new ArrayList<>();
        for (Edge e : g.getEdges()) {
            int f = g.getDegree(e.source) +
                    g.getDegree(e.target) - 2;
            all.add(f);
        }
        Collections.sort(all);
        maxEdge = all.get(all.size()-1);
        if (all.size()-2 >= 0) {
            maxEdge2 = all.get(all.size()-2);
        } else {
            maxEdge2 = maxEdge;
        }

        double M12 = zif.getSecondZagreb(1);
        double M21 = zif.getFirstZagreb(1);
        double M31 = zif.getFirstZagreb(2);
        double EM31 = zifL.getFirstZagreb(2);

        List<Object> v = new ArrayList<>();
        
      // Milo Errors 2018
       // v.add(m*minEdge);
      //  v.add(M21*minEdge);
      //  v.add(4*M12*minEdge);
       // v.add((M31+(2*M12))*minEdge);
     //   v.add(m*minEdge/(maxEdge*maxEdge));
        v.add(EM31);
        v.add( (((M31+(2*M12)-(3*M21))*(M31+(2*M12)-(3*M21)) ) +(M21*((3*M21-(8*m)))) + (maxEdge*maxEdge2*(maxEdge-maxEdge2)*(maxEdge-maxEdge2)) )/M21 );
      //  v.add(m*maxEdge/(minEdge*minEdge));
      //  v.add((M31+(2*M12))*maxEdge);
     //   v.add(2*M31*maxEdge);
      //  v.add(M21*minEdge);
       // v.add(m*maxEdge);

       // v.add(zifL.getFirstZagreb(1));

        //new1+-----------
       // v.add(M31-(4*maxDeg*maxDeg)-(4*maxDeg2*maxDeg2)-(4*Psi1)+(2*M12)+(4*m));


        //new2
      //  v.add(M31-(4*maxDeg*maxDeg)-(4*minDeg*minDeg)-(4*Psi1)+(2*M12)+(4*m));

        //new3
     //   v.add((M21*(n-4))+(4*M12)-(4*m*m)+(4*m));

        //N4
   //     v.add((M21-(2*m))*(m+(2*minDeg)-3)-(2*m*(m-1)*(minDeg-1)));

        //N3
        //v.add(((maxDeg+minDeg-2)*(maxDeg+minDeg-2)*(M21-2*m)*(M21-2*m))/(4*m*(maxDeg-1)*(minDeg-1)));

        //N2
    //    v.add((2*(maxDeg+minDeg-2)*M21)-(4*m*(maxDeg*minDeg-1)));

        //N1
     //   v.add(4*m*(maxDeg-1)*(maxDeg-1));
        
        // Milo Error.
        // v.add( ((M21 - (2*m))*(M21 - (2*m))/m) +( (maxEdge-minEdge)*(maxEdge-minEdge)/2) );
        //Theorem 1
    //    int k = KConnected.kconn(g);
    //    v.add(k*Math.pow(k+n-3,2)
       //         + 4*(n-2)*(n-2)* Utils.choose(k,2).intValue()
       //         + 4*(n-3)*(n-3)*Utils.choose((int) (n-k-1),2).intValue()
        //        + k*(n-k-1)*Math.pow(2*n-5,2));
        ret.add(v);
        return ret;
    }

    @Override
    public String getCategory() {
        return "Verification-Degree";
    }
}