/*
 * Yet Another UserAgent Analyzer
 * Copyright (C) 2013-2020 Niels Basjes
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package nl.basjes.parse.useragent.utils;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class TestNormalize {

    @Test
    public void checkBrandEdgeCases() {
        assertNull(Normalize.brand(null));
        assertEquals("", Normalize.brand(""));
    }

    @Test
    public void checkBrandOne() {
        assertEquals("N", Normalize.brand("n"));
        assertEquals("N", Normalize.brand("N"));
    }

    @Test
    public void checkBrandTwo() {
        assertEquals("NB", Normalize.brand("nb"));
        assertEquals("NB", Normalize.brand("nB"));
        assertEquals("NB", Normalize.brand("Nb"));
        assertEquals("NB", Normalize.brand("NB"));
    }

    @Test
    public void checkBrandThree() {
        assertEquals("NBA", Normalize.brand("nba"));
        assertEquals("NBA", Normalize.brand("nBa"));
        assertEquals("NBA", Normalize.brand("Nba"));
        assertEquals("NBA", Normalize.brand("NBA"));
    }

    @Test
    public void checkBrandThreeFour() {
        assertEquals("NBA/Klmn", Normalize.brand("nba/kLmN"));
        assertEquals("NBA/Klmn", Normalize.brand("nBa/KlMn"));
        assertEquals("NBA/Klmn", Normalize.brand("Nba/klmn"));
        assertEquals("NBA/Klmn", Normalize.brand("NBA/KLMN"));
    }

    @Test
    public void checkBrandNormalizationWord() {
        assertEquals("Niels", Normalize.brand("niels"));
        assertEquals("Niels", Normalize.brand("Niels"));
        assertEquals("Niels", Normalize.brand("NiElS"));
        assertEquals("Niels", Normalize.brand("nIELS"));
        assertEquals("Niels", Normalize.brand("NIELS"));
    }

    @Test
    public void checkBrandNormalizationExamples() {
        // At least 3 lowercase
        assertEquals("NielsBasjes",      Normalize.brand("NielsBasjes"));
        assertEquals("NielsBasjes",      Normalize.brand("NIelsBasJES"));
        assertEquals("BlackBerry",       Normalize.brand("BlackBerry"));

        // Less than 3 lowercase
        assertEquals("Nielsbasjes",      Normalize.brand("NIelSBasJES"));
        assertEquals("Blackberry",       Normalize.brand("BLACKBERRY"));

        // Multiple words. Short words (1,2,3 letters) go full uppercase
        assertEquals("Niels NBA Basjes", Normalize.brand("NIels NbA BasJES"));
        assertEquals("LG",               Normalize.brand("lG"));
        assertEquals("HTC",              Normalize.brand("hTc"));
        assertEquals("Sony",             Normalize.brand("sOnY"));
        assertEquals("Asus",             Normalize.brand("aSuS"));
    }

    @Test
    public void checkCombiningDeviceNameAndBrand() {
        assertEquals("Asus Something T123",     Normalize.cleanupDeviceBrandName("AsUs", "something t123"));
        assertEquals("Sony X1",                 Normalize.cleanupDeviceBrandName("Sony", "sony x1"));
        assertEquals("Sony X1",                 Normalize.cleanupDeviceBrandName("Sony", "sony-x1"));
        assertEquals("Sony X1",                 Normalize.cleanupDeviceBrandName("Sony", "sonyx1"));
        assertEquals("HP SlateBook 10 X2 PC",   Normalize.cleanupDeviceBrandName("hP", "SlateBook 10 X2 PC"));
        assertEquals("Samsung GT-1234",         Normalize.cleanupDeviceBrandName("Samsung", "GT - 1234"));
    }

    @Test
    public void checkEmailNormalization() {
        assertEquals("[email protected]",                   Normalize.email("support [at] zite [dot] com"));
        assertEquals("[email protected]",               Normalize.email("austin at affectv dot co dot uk"));
        assertEquals("[email protected]",                 Normalize.email("epicurus at gmail dot com"));
        assertEquals("[email protected]",             Normalize.email("buibui[dot]bot[\\xc3\\xa07]moquadv[dot]com"));
        assertEquals("[email protected]",      Normalize.email("maxpoint.crawler at maxpoint dot com"));
        assertEquals("[email protected]",                       Normalize.email("[email protected]"));
        assertEquals("[email protected]",                Normalize.email("crawler at example dot com"));
        assertEquals("[email protected]",                   Normalize.email("yelpbot at yelp dot com"));
        assertEquals("[email protected]",                   Normalize.email("support [at] zite [dot] com"));
        assertEquals("[email protected]",                Normalize.email("support [at] safedns [dot] com"));
        assertEquals("[email protected]",      Normalize.email("search_comments\\at\\sensis\\dot\\com\\dot\\au"));
        assertEquals("[email protected]",  Normalize.email("mms dash crawler dash support at yahoo dash inc dot com"));
    }

    @Test
    public void checkBadInputData() {
        // This used to trigger an exception in the underlying RegEx.
        assertNotNull(Normalize.cleanupDeviceBrandName("${N", "${N.Foo"));
    }

    @Test
    public void checkIsLowerCase() {
        assertTrue(Normalize.isLowerCase("basjes0123456789`[email protected]#$%^&*()_-+={}[];:'\",.<>/?"));

        assertTrue(Normalize.isLowerCase("niels"));
        assertTrue(Normalize.isLowerCase("basjes"));

        assertFalse(Normalize.isLowerCase("Basjes"));
        assertFalse(Normalize.isLowerCase("bAsjes"));
        assertFalse(Normalize.isLowerCase("baSjes"));
        assertFalse(Normalize.isLowerCase("basJes"));
        assertFalse(Normalize.isLowerCase("basjEs"));
        assertFalse(Normalize.isLowerCase("basjeS"));
        assertFalse(Normalize.isLowerCase("BASJES"));
    }
}