package games.colonier.ld44.chemistry;

import java.util.*;

public final class DiseaseGenerator {

    private DiseaseGenerator () {
        throw new UnsupportedOperationException ();
    }

    private static Molecule randomMolecule (int minAtoms, int maxAtoms) {

        Molecule molecule = new Molecule (1);

        Random random = new Random ();
        int nAtoms = random.nextInt (maxAtoms - minAtoms) + minAtoms;

        for (int i = 0; i < nAtoms; i++) {

            Atom atom = new Atom (i, Atom.Type.values ()[random.nextInt (Atom.Type.values ().length)]);
            molecule.atoms.add (atom);

        }

        while (!molecule.isConnected ()) {

            Atom a1 = molecule.atoms.get (random.nextInt (molecule.atoms.size ()));
            Atom a2 = molecule.atoms.get (random.nextInt (molecule.atoms.size ()));

            if (!a1.equals (a2)) {
                a1.connect (a2);
            }

        }

        return molecule;

    }

    public static Molecule generate (int nSymptoms) {

        Molecule molecule = new Molecule (1);
        Random random = new Random ();
        int nRandom = 2;

        List<List<Atom>> symptomFormations = new ArrayList<> ();
        Set<Symptom> usedSymptoms = new HashSet<> ();
        int id = 1;
        Symptom symptom = Symptom.values ()[random.nextInt (Symptom.values ().length)];

        for (int i = 0; i < nSymptoms; i++) {

            if (!usedSymptoms.add (symptom) && usedSymptoms.size () > 1) {
                i--;
                System.out.println ("DiseaseGenerator : ALREADY USED SYMPTOM");
                symptom = Symptom.values ()[random.nextInt (Symptom.values ().length)];
                continue;
            }

            List<String> commands = new ArrayList<> ();
            for (int j = 0; j < symptom.rule.expression.length () / 2; j++) {
                commands.add (symptom.rule.expression.substring (2 * j, 2 * (j + 1)));
            }

            List<Atom> atoms = new ArrayList<> ();
            Atom cur = null;
            Atom prev = null;
            for (int j = 0; j < commands.size (); j++) {

                String command = commands.get (j);
                String from = command.substring (0, 1);
                String to = command.substring (1, 2);

                if (cur == null) {

                    if ("R".equalsIgnoreCase (from)) {
                        prev = new Atom (id++, Atom.Type.Red);
                    } else if ("G".equalsIgnoreCase (from)) {
                        prev = new Atom (id++, Atom.Type.Green);
                    } else if ("B".equalsIgnoreCase (from)) {
                        prev = new Atom (id++, Atom.Type.Blue);
                    }

                    if ("R".equalsIgnoreCase (to)) {
                        cur = new Atom (id++, Atom.Type.Red);
                    } else if ("G".equalsIgnoreCase (to)) {
                        cur = new Atom (id++, Atom.Type.Green);
                    } else if ("B".equalsIgnoreCase (to)) {
                        cur = new Atom (id++, Atom.Type.Blue);
                    }

                    atoms.add (prev);
                    atoms.add (cur);

                    prev.connect (cur);

                } else {

                    prev = cur;
                    if ("R".equalsIgnoreCase (to)) {
                        cur = new Atom (id++, Atom.Type.Red);
                    } else if ("G".equalsIgnoreCase (to)) {
                        cur = new Atom (id++, Atom.Type.Green);
                    } else if ("B".equalsIgnoreCase (to)) {
                        cur = new Atom (id++, Atom.Type.Blue);
                    }

                    atoms.add (cur);

                    prev.connect (cur);

                }

            }

            Molecule test = new Molecule (0);
            test.atoms.addAll (atoms);
            if (!symptom.rule.appliesTo (test)) {
                System.out.println ("DiseaseGenerator : WRONG SYMPTOM FORMATION");
                i--;
                continue;
            }

            symptomFormations.add (atoms);

            symptom = Symptom.values ()[random.nextInt (Symptom.values ().length)];

        }

        List<Atom> allAtoms = new ArrayList<> ();
        for (List<Atom> list : symptomFormations) {
            allAtoms.addAll (list);
        }

        for (int i = 0; i < nRandom; i++) {

            allAtoms.add (
                    new Atom (
                            id++,
                            Atom.Type.values ()[random.nextInt (Atom.Type.values ().length)]
                    )
            );

        }

        molecule.atoms.addAll (allAtoms);

        while (!molecule.isConnected ()) {

            do {

                Atom a1 = molecule.atoms.get (random.nextInt (molecule.atoms.size ()));
                Atom a2 = molecule.atoms.get (random.nextInt (molecule.atoms.size ()));

                if (!a1.equals (a2)) {
                    a1.connect (a2);
                    System.out.println ("DiseaseGenerator : CONNECTED LOOP BREAKING");
                    break;
                }

                System.out.println ("DiseaseGenerator : CONNECTED LOOP");

            } while (true);

        }

        molecule.arrangeAtoms ();

        return molecule;

    }

}
