/*
 * -----------------------------------------------------------------------------
 * COPYRIGHT (C) 2019, FONTEVA, INC.
 * ALL RIGHTS RESERVED.
 *
 * ALL INFORMATION CONTAINED HEREIN IS, AND REMAINS THE PROPERTY OF FONTEVA
 * INCORPORATED AND ITS SUPPLIERS, IF ANY. THE INTELLECTUAL AND TECHNICAL
 * CONCEPTS CONTAINED HEREIN ARE PROPRIETARY TO FONTEVA INCORPORATED AND
 * ITS SUPPLIERS AND MAY BE COVERED BY U.S. AND FOREIGN PATENTS, PATENTS IN
 * PROCESS, AND ARE PROTECTED BY TRADE SECRET OR COPYRIGHT LAW. DISSEMINATION
 * OF THIS INFORMATION OR REPRODUCTION OF THIS MATERIAL IS STRICTLY FORBIDDEN
 * UNLESS PRIOR WRITTEN PERMISSION IS OBTAINED FROM FONTEVA, INC.
 * -----------------------------------------------------------------------------
 */

@IsTest
public with sharing class PfmSetUtilsTest {
    class Foo {
        public Foo(String foo, String bar) {
            this.foo = foo;
            this.bar = bar;
        }
        public String foo;
        public String bar;
    }

    @IsTest
    static void testGetIds() {
        String idStr = '0036g000003CtXdAAK';
        List<Contact> contacts = new List<Contact>{
            new Contact(LastName = 'Visser', Id = idStr),
            new Contact(LastName = 'Gurp', Id = '0036g000003CtXf')
        };

        Set<Id> ids = PfmSetUtils.getIds(contacts);
        System.assertEquals(2, ids.size());
        System.assert(ids.contains(idStr));

        List<Id> idList = PfmSetUtils.getIdList(contacts);
        System.assertEquals(2, idList.size());
        System.assertEquals(2, PfmSetUtils.toList(ids).size());
        System.assert(idList.contains(idStr), JSON.serialize(idList));
        System.assert(PfmSetUtils.toList(ids).contains(idStr));
    }

    @IsTest
    static void testFilter() {
        String idStr = '0036g000003CtXd';
        List<Contact> contacts = new List<Contact>{
            new Contact(LastName = 'Visser', FirstName = 'Andy', Id = idStr),
            new Contact(LastName = 'Gurp', Id = '0036g000003CtXf')
        };

        contacts = PfmSetUtils.filter(contacts, 'LastName', 'Visser');

        System.assertEquals(1, contacts.size());
        System.assertEquals('Andy', contacts.get(0).FirstName);
    }

    @IsTest
    static void testFilterString() {
        List<String> strs = new List<String>{ 'foobar', 'foo manchu', 'a great disaster' };

        System.assertEquals(2, PfmSetUtils.filterStrings(strs, 'foo.*').size());
        System.assertEquals(1, PfmSetUtils.filterStrings(strs, 'foobar').size());
        System.assertEquals('foobar', PfmSetUtils.filterStrings(strs, 'foobar')[0]);
        System.assertEquals(0, PfmSetUtils.filterStrings(strs, 'cornholio').size());
    }

    @IsTest
    static void testTrim() {
        List<String> strs = new List<String>{ 'foobar   ', '  foo manchu', 'a great disaster' };

        List<String> results = PfmSetUtils.trim(strs);
        System.assertEquals('foobar', results[0]);
        System.assertEquals('foo manchu', results[1]);
        System.assertEquals('a great disaster', results[2]);
    }

    @IsTest
    static void testFilterNotEmpty() {
        List<String> strs = new List<String>{ 'foobar', '', null, 'a great disaster' };

        List<String> results = PfmSetUtils.filterNotEmpty(strs);
        System.assertEquals(2, results.size());
        System.assertEquals('foobar', results[0]);
        System.assertEquals('a great disaster', results[1]);
    }

    @IsTest
    static void testMapToLower() {
        List<String> strs = new List<String>{ 'FooBar', 'foobar', 'A Great Disaster', '', null };

        List<String> results = PfmSetUtils.mapToLower(strs);
        System.assertEquals(5, results.size());
        System.assertEquals('foobar', results[0]);
        System.assertEquals('foobar', results[1]);
        System.assertEquals('a great disaster', results[2]);
    }

    @IsTest
    static void testMapString() {
        List<String> strs = new List<String>{ 'foobar', 'barbaz' };

        List<String> results = PfmSetUtils.mapStrings(strs, 'foo(.*)', 'foo.$1');
        System.assertEquals(2, results.size());
        System.assertEquals('foo.bar', results[0]);
        System.assertEquals(null, results[1]);

        results = PfmSetUtils.mapStrings(strs, 'barbaz', 'donkey');
        System.assertEquals(2, results.size());
        System.assertEquals(null, results[0]);
        System.assertEquals('donkey', results[1]);
    }

    @IsTest
    static void testFindChild() {
        Account myCorp = new Account(Name = 'my corp');
        Account fon = new Account(Name = 'fonCorp');
        List<Account> accts = new List<Account>{ myCorp, fon };
        insert accts;
        List<Contact> contacts = new List<Contact>{
            new Contact(LastName = 'Visser', AccountId = myCorp.Id),
            new Contact(LastName = 'Gurp', AccountId = fon.Id)
        };
        insert contacts;

        contacts = [SELECT LastName, Account.Name FROM Contact];

        Contact foundContact = (Contact) PfmSetUtils.findByRelatedField(contacts, 'Account.Name', 'my corp');

        System.assertEquals('my corp', foundContact.Account.Name);
        System.assertEquals('Visser', foundContact.LastName);
    }

    @IsTest
    static void testMapChild() {
        Account myCorp = new Account(Name = 'my corp');
        Account fon = new Account(Name = 'fonCorp');
        List<Account> accts = new List<Account>{ myCorp, fon };
        insert accts;
        List<Contact> contacts = new List<Contact>{
            new Contact(LastName = 'Visser', AccountId = myCorp.Id),
            new Contact(LastName = 'Gurp', AccountId = fon.Id)
        };
        insert contacts;

        contacts = [SELECT LastName, Account.Name FROM Contact];

        List<Object> acctNames = PfmSetUtils.mapToRelatedField(contacts, 'Account.Name');

        System.assertEquals('my corp', acctNames[0]);
        System.assertEquals('fonCorp', acctNames[1]);
    }

    @IsTest
    static void testAsIds() {
        List<Object> objects = new List<Object>{ '0036g000003CtXf', '0036g000003CtXd' };

        List<Id> ids = PfmSetUtils.asIds(objects);

        System.assertEquals(2, ids.size());
        System.assertEquals(ids.get(0), Id.valueOf('0036g000003CtXf'));
    }

    @IsTest
    static void testBucketById() {
        List<Contact> contacts = new List<Contact>{
            new Contact(LastName = 'Sam', AccountId = '0016g000003CtXd'),
            new Contact(LastName = 'Avi', AccountId = '0016g000003CtXd'),
            new Contact(LastName = 'JKim', AccountId = '0016g000003CtXe'),
            new Contact(LastName = 'Visser', AccountId = '0016g000003CtXf'),
            new Contact(LastName = 'Gurp', AccountId = '0016g000003CtXf')
        };

        Map<Id, List<Contact>> bucketedContacts = (Map<Id, List<Contact>>) PfmSetUtils.bucketById(
            contacts,
            'AccountId'
        );

        System.assertEquals(2, bucketedContacts.get('0016g000003CtXd').size());
        System.assertEquals(1, bucketedContacts.get('0016g000003CtXe').size());
        System.assertEquals(2, bucketedContacts.get('0016g000003CtXf').size());
        System.assertEquals('JKim', bucketedContacts.get('0016g000003CtXe').get(0).LastName);
    }

    @IsTest
    static void testGetField() {
        List<Foo> foos = new List<Foo>{ new Foo('foo', 'bar'), new Foo('foo', 'baz') };

        List<String> results = PfmSetUtils.mapToString(foos, 'bar');
        System.assertEquals('bar', results[0]);
        System.assertEquals('baz', results[1]);
    }

    @IsTest
    static void testFind() {
        Contact v = new Contact(LastName = 'Visser');
        List<Contact> contacts = new List<Contact>{ v, new Contact(LastName = 'Gurp') };

        System.assertEquals(v, PfmSetUtils.find(contacts, 'LastName', 'Visser'));
        System.assertEquals(null, PfmSetUtils.find(contacts, 'LastName', 'Sandy'));
    }
}
