<html>

<head>
    <script>
        /*
            TODO: 
                - Incorporate the courses (after adding more); 
                - randomly add a second non-duplticating affliate
        */

        // https://stackoverflow.com/a/424445
        function RNG(seed) {
        // LCG using GCC's constants
        this.m = 0x80000000; // 2**31;
        this.a = 1103515245;
        this.c = 12345;

        this.state = seed ? seed : Math.floor(Math.random() * (this.m - 1));
        }
        RNG.prototype.nextInt = function() {
        this.state = (this.a * this.state + this.c) % this.m;
        return this.state;
        }
        RNG.prototype.nextFloat = function() {
        // returns in range [0,1]
        return this.nextInt() / (this.m - 1);
        }
        RNG.prototype.nextRange = function(start, end) {
        // returns in range [start, end): including start, excluding end
        // can't modulu nextInt because of weak randomness in lower bits
        var rangeSize = end - start;
        var randomUnder1 = this.nextInt() / this.m;
        return start + Math.floor(randomUnder1 * rangeSize);
        }
        RNG.prototype.choice = function(array) {
        return array[this.nextRange(0, array.length)];
        }

        var surnames = ["Gasper", "Smith", "Anderson", "Roberts", "Davis", "Brown", "Langenberg", "Vales",
            "Grady", "Doe", "Morrison", "Walters", "Johnson", "Williams", "Peterson", "Martinez", "Thompson",
            "White", "Lee", "Clark", "Lewis", "Lopez", "Gonazles", "Scott", "Henderson", "Butler", "Price",
            "Nielson"
        ];

        var givenNames = ["John", "Michael", "Jennifer", "Nancy", "Bill", "William",
            "Kiersten", "Marie", "Lori", "Mark", "Eric", "David", "Ann",
            "Donna", "Paul", "Thomas", "Robert", "David", "Jim", "James",
            "Blake", "Sarah", "Karoline", "Kim", "Erik", "Greg", "Karl",
            "Colin", "Jo", "Betty", "Lisa", "Heather", "Mary", "Stephanie", "Christina",
            "Christopher", "Jeremy", "Nancy", "Amber", "Adian", "Perry", "Steve",
            "Andrew", "Megan", "Anna", "Claire", "Maddie", "Madison", "Debbie", "Lexi", 
            "Olivia", "Emma", "Ava", "Sophia", "Isabella", "Mia"
        ];

        var departments = ["Computer Science", "Engineering", "Business", "Accounting",
            "Law", "Physical Education", "Language Arts", "Financial Aid",
            "Information Technology", "Advising", "Purchasing", "Accounts Payable"
        ];

        var affiliations = ["student", "staff", "faculty", "alum", "community"];

        var courses = ["ACCT101", "ACCT201", "MATH100", "MATH101", "CS251", "CS252", 
        "ENGL101", "ENGL102", "ENGL201", "HIST101", "HIST102",
        "SCI123", "SCI123", "SCI404"
        ];

        var rng;

        function generateData() {
            var people = [];

            var seed = parseInt(document.getElementById('seed').value);
            rng = new RNG(seed);

            var personCount = parseInt(document.getElementById('count').value) - 1;
            var peopleOu = document.getElementById('people_ou').value;

            for (i = 0; i <= personCount; i++) {
                surname = surnames[rng.nextRange(0, surnames.length)];
                givenName = givenNames[rng.nextRange(0, givenNames.length)];
                idNumber = "8" + (i + 1).toString().padStart(7, "0");

                uid = givenName[0] + surname + i;

                var person = {
                    uid: uid.toLowerCase(),
                    surname: surname,
                    givenName: givenName,
                    idNumber: idNumber,
                };

                people.push(person);
            }

            //Add additional randomized characteristics sets here; 
            //keep the ordering the same to maintain deterministic capabilities between runs

            //Assign departments
            for (index = 0; index < people.length; ++index) {
                people[index]["department"] = departments[rng.nextRange(0, departments.length)];
            }

            //Assign affiliations
            for (index = 0; index < people.length; ++index) {
                people[index]["affiliations"] = selectUnduplicated(affiliations, 2);
            }

            //Assign titles/primary affiliations
            for (index = 0; index < people.length; ++index) {
                people[index]["title"] = rankAffiliations(people[index].affiliations);
            }

            //Create Course Enrollments
            for (index = 0; index < people.length; ++index) {
                people[index]["courses"] = [];
                if (people[index]["affiliations"].indexOf("student") > -1 
                        || people[index]["affiliations"].indexOf("faculty") > -1) {
                    people[index]["courses"] = selectUnduplicated(courses, 4);
                }
            }

            //Create vpn_users 
            for (index = 0; index < people.length; ++index) {
                people[index].vpn_user = people[index].affiliations.indexOf('staff') >= 0 || people[index].affiliations.indexOf('faculty') >= 0 ?
                    (rng.nextFloat() > 0.1): //grab most faculty and staff
                    rng.nextFloat() > 0.9; // and only a few others
            }

            //Create vpn users ldap group
            makeQuestionableVpnUsersLists(people);

            //Create Athletics users
            makeAthleticsUsersLists(people);

            //Create lists of non-faculty (staff) banner users
            makeNonFacultyBannerUsersLists(people);

            //Create lists of visiting scholars
            makeVisitingScholarsLists(people);

            console.log(people);

            //Generate Output
            var ldif = "";
            for (j = 0; j < people.length; j++) {
                ldif += formatPersonLdif(people[j], peopleOu);
            }
            ldif += formatVpnUsersGroupLdif(people, peopleOu);
            ldif += formatCommunityGroupLdif(people, peopleOu);
            document.getElementById('ldif').value = ldif;

            var sql = "";
            sql += sqlHeader();
            for (k = 0; k < people.length; k++) {
                sql += formatSqlSubjects(people[k]);
                sql += formatSqlCourses(people[k]);
            }
            document.getElementById('sql').value = sql;
        }

        function formatPersonLdif(person, ou) {
            var output =
                "dn: uid=<uid>," + ou + "\n" +
                "objectClass: organizationalPerson\n" +
                "objectClass: person\n" +
                "objectClass: top\n" +
                "objectClass: inetOrgPerson\n" +
                "objectClass: eduPerson\n" +
                "surname: <surname>\n" +
                "givenName: <givenName>\n" +
                "cn: <givenName> <surname>\n" +
                "uid: <uid>\n" +
                "title: <title>\n" +
                "employeeNumber: <idNumber>\n" +
                "mail: <uid>@example.edu\n" +
                "businessCategory:<department>\n" +
                "userPassword: password\n";

            output = output.replace(/<uid>/g, person.uid);
            output = output.replace(/<surname>/g, person.surname);
            output = output.replace(/<givenName>/g, person.givenName);
            output = output.replace(/<department>/g, person.department);
            output = output.replace(/<title>/g, person.title);
            output = output.replace(/<idNumber>/g, person.idNumber);

            for (i = 0; i < person.affiliations.length; i++) {
                output += "eduPersonAffiliation: " + person.affiliations[i] + "\n";
            }

            return output + "\n";
        }

        function formatVpnUsersGroupLdif(people, ou) {
            var vpnOutput =
            "dn: cn=vpn_users,ou=groups,dc=internet2,dc=edu\n" +
            "objectClass: groupOfNames\n" +
            "objectClass: top\n" +
            "cn: vpn_users\n"

            for (j = 0; j < people.length; j++) {
                if (people[j].vpn_user == 1) {
                    vpnOutput = vpnOutput + "member: uid=" + people[j].uid + ',' + ou + "\n"
                }
            }

            return vpnOutput + "\n";
        }

        function formatCommunityGroupLdif(people, ou) {
            var vpnOutput =
            "dn: cn=community_members,ou=groups,dc=internet2,dc=edu\n" +
            "objectClass: groupOfNames\n" +
            "objectClass: top\n" +
            "cn: community_members\n"

            for (j = 0; j < people.length; j++) {
                if (people[j].affiliations.indexOf('community') >= 0 ) {
                    vpnOutput = vpnOutput + "member: uid=" + people[j].uid + ',' + ou + "\n"
                }
            }

            return vpnOutput + "\n";
        }


        function sqlHeader() {
            return "CREATE TABLE SIS_COURSES (\n" +
                "  termId varchar(255) NOT NULL,\n" +
                "  courseId varchar(255) NOT NULL,\n" +
                "  studentId varchar(255) NOT NULL,\n" +
                "  PRIMARY KEY (termId, courseId, studentId)\n" +
                ");\n\n" +
                "CREATE TABLE HR_PEOPLE (\n" +
                "  id varchar(255) NOT NULL,\n" +
                "  surname varchar(255) default NULL,\n" +
                "  givenName varchar(255) default NULL,\n" +
                "  PRIMARY KEY (id)\n" +
                ");\n\n" + 
                "CREATE TABLE HR_PEOPLE_ROLES (\n" +
                "  id varchar(255) NOT NULL,\n" +
                "  role varchar(255) NOT NULL,\n" +
                "  PRIMARY KEY (id, role)\n" +
                ");\n\n";
        }

        function formatSqlCourses(person) {
            var template =
                "INSERT INTO SIS_COURSES (termId, courseId, studentId) " +
                "VALUES ('201810','<courseId>','<id>');\n";

            var output = "";

            for (i = 0; i < person.courses.length; i++) {
                temp = template.replace(/<id>/g, person.idNumber);
                temp = temp.replace(/<courseId>/g, person.courses[i]);
                output += temp;
            }

            return output;
        }

        function formatSqlSubjects(person) {
            var template =
                "INSERT INTO HR_PEOPLE(id, surname, givenName) " +
                "VALUES ('<id>','<surname>','<givenName>');\n";

            var output = "";

            temp = template.replace(/<id>/g, person.idNumber);
            temp = temp.replace(/<surname>/g, person.surname);
            temp = temp.replace(/<givenName>/g, person.givenName);
            output += temp;
            
            var template =
                "INSERT INTO HR_PEOPLE_ROLES(id, role) " +
                "VALUES ('<id>','<role>');\n";

            for (i = 0; i < person.affiliations.length; i++) {
                var template =
                "INSERT INTO HR_PEOPLE_ROLES(id, role) " +
                "VALUES ('<id>','<role>');\n";

                if (person.affiliations[i] == 'staff' 
                        || person.affiliations[i] == 'faculty'
                        || person.affiliations[i] =='student'
                        || person.affiliations[i] =='community') {
                    temp = template.replace(/<id>/g, person.idNumber);
                    temp = temp.replace(/<role>/g, person.affiliations[i]);
                    output += temp;
                }
            }

            return output;
        }

        function selectUnduplicated(source, max) {
            var output = [];

            count = rng.nextRange(0, max) + 1;
            
            while (output.length < count) {
                item = source[rng.nextRange(0, source.length)];
                
                if (output.indexOf(item) == -1) {
                    output.push(item);
                }
            }

            return output;
        }

        function rankAffiliations(affiliations) {
            if (affiliations.indexOf("faculty") > -1)
                return "faculty";
            else if (affiliations.indexOf("staff") > -1)
                return "staff";
            else if (affiliations.indexOf("student") > -1)
                return "student";
            else if (affiliations.indexOf("alum") > -1)
                return "alum";
            else
                return "other";
        }

        function makeQuestionableVpnUsersLists(people) {
            var csvOutput = "";
            var gshOutput = 'addGroup("test", "cisoQuestionableVpnUsersList", "CISO VPN Questionable VPN List");\n';
            var sampleCount = 15;

            for (i = 0; i < people.length && sampleCount >  0; i++) {
                if (people[i].vpn_user == true & rng.nextFloat() > 0.75) {
                    csvOutput = csvOutput + people[i].uid + "\n";
                    gshOutput = gshOutput + 'addMember("test:cisoQuestionableVpnUsersList","' + people[i].uid + '");\n';
                    sampleCount--;
                }
            }

            document.getElementById('vpnCsv').value = csvOutput;
            document.getElementById('vpnGsh').value = gshOutput;
        }

        function makeAthleticsUsersLists(people) {
            var csvOutput = "";
            var gshOutput = 'addGroup("app:mfa:ref", "athletics_dept", "athletics_dept");\n';
            var sampleCount = 15;

            for (i = 0; i < people.length && sampleCount >  0; i++) {
                if (people[i].affiliations.indexOf('staff') >= 0 & rng.nextFloat() > 0.75) {
                    csvOutput = csvOutput + people[i].uid + "\n";
                    gshOutput = gshOutput + 'addMember("app:mfa:ref:athletics_dept","' + people[i].uid + '");\n';
                    sampleCount--;
                }
            }

            document.getElementById('athleticsCsv').value = csvOutput;
            document.getElementById('athleticsGsh').value = gshOutput;
        }

        function makeNonFacultyBannerUsersLists(people) {
            var csvOutput = "";
            var gshOutput = 'addGroup("app:mfa:ref", "NonFacultyBannerINB", "NonFacultyBannerINB");\n';
            var sampleCount = 35;

            for (i = 100; i < people.length && sampleCount >  0; i++) {
                if (people[i].affiliations.indexOf('staff') >= 0 & rng.nextFloat() > 0.75) {
                    csvOutput = csvOutput + people[i].uid + "\n";
                    gshOutput = gshOutput + 'addMember("app:mfa:ref:NonFacultyBannerINB","' + people[i].uid + '");\n';
                    sampleCount--;
                }
            }

            document.getElementById('bannerCsv').value = csvOutput;
            document.getElementById('bannerGsh').value = gshOutput;
        }

        function makeVisitingScholarsLists(people) {
            var csvOutput = "";
            var gshOutput = 'addGroup("app:lms:ref", "visiting_scholars", "visiting_scholars");\n';
            var sampleCount = 25;

            for (i = 300; i < people.length && sampleCount >  0; i++) {
                if (people[i].affiliations.indexOf('community') >= 0) {
                    csvOutput = csvOutput + people[i].uid + "\n";
                    gshOutput = gshOutput + 'addMember("app:lms:ref:visiting_scholars","' + people[i].uid + '");\n';
                    sampleCount--;
                }
            }

            document.getElementById('visitingScholarsCsv').value = csvOutput;
            document.getElementById('visitingScholarsGsh').value = gshOutput;
        }

    </script>
</head>

<body>
    <form>
        Seed: <input type="text" name="seed" id="seed" value="6874" /> <br />
        Number of Subjects: <input type="text" name="count" id="count" value="1000" /> <br />
        People OU: <input type="text" name="people_ou" id="people_ou" value="ou=people,dc=internet2,dc=edu"/> <br />
        <input type="button" onclick="generateData(); return false;" value="Run" /> <br />
    </form>

    <p>
        Ldif: <br /><textarea cols="100" rows="15" id="ldif"></textarea><br />
    </p>
    <p>
        Sql: <br /><textarea cols="100" rows="15" id="sql"></textarea> <br />
    </p>
    <p>
        Questionable VPN Users CSV: <br /><textarea cols="100" rows="15" id="vpnCsv"></textarea> <br />
    </p>
    <p>
        Questionable VPN Users GSH: <br /><textarea cols="100" rows="15" id="vpnGsh"></textarea> <br />
    </p>

    <p>
        Athletic Dept CSV: <br /><textarea cols="100" rows="15" id="athleticsCsv"></textarea> <br />
    </p>
    <p>
        Atheltics Dept GSH: <br /><textarea cols="100" rows="15" id="athleticsGsh"></textarea> <br />
    </p>
    <p>
        Non-faculty Banner Users CSV: <br /><textarea cols="100" rows="15" id="bannerCsv"></textarea> <br />
    </p>
    <p>
        Non-faculty Banner Users GSH: <br /><textarea cols="100" rows="15" id="bannerGsh"></textarea> <br />
    </p>
    <p>
        Visiting Scholars Users CSV: <br /><textarea cols="100" rows="15" id="visitingScholarsCsv"></textarea> <br />
    </p>
    <p>
        Visiting Scholars Users GSH: <br /><textarea cols="100" rows="15" id="visitingScholarsGsh"></textarea> <br />
    </p>

</body>

</html>