// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui;

import static org.junit.Assert.*

import org.junit.BeforeClass
import org.junit.Test
import org.openstreetmap.josm.JOSMFixture
import org.openstreetmap.josm.Main
import org.openstreetmap.josm.data.osm.UserInfo

class JosmUserIdentityManagerTest {

    final shouldFail = new GroovyTestCase().&shouldFail

    @BeforeClass
    public static void initTestCase() {
        JOSMFixture.createUnitTestFixture().init()
    }

    @Test
    public void test_SingletonAccess() {

        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        // created ?
        assert im != null

        // registered as listener ?
        assert Main.pref.@listeners.contains(im)

        JosmUserIdentityManager im2 = JosmUserIdentityManager.getInstance()

        // only one instance
        assert im == im2
    }

    @Test
    public void test_setAnonymouse() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        im.setPartiallyIdentified "test"
        im.setAnonymous()

        assert im.isAnonymous()
        assert ! im.isPartiallyIdentified()
        assert ! im.isFullyIdentified()

        assert im.getUserId() == 0
        assert im.getUserName() == null
        assert im.getUserInfo() == null
    }

    @Test
    public void test_setPartiallyIdentified() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        im.setPartiallyIdentified "test"

        shouldFail(IllegalArgumentException) {
            im.setPartiallyIdentified null
        }

        shouldFail(IllegalArgumentException) {
            im.setPartiallyIdentified ""
        }

        shouldFail(IllegalArgumentException) {
            im.setPartiallyIdentified "  \t  "
        }

        im.setPartiallyIdentified "test"

        assert ! im.isAnonymous()
        assert im.isPartiallyIdentified()
        assert ! im.isFullyIdentified()

        assert im.getUserId() == 0
        assert im.getUserName() == "test"
        assert im.getUserInfo() == null
    }


    @Test
    public void test_setFullyIdentified() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        UserInfo userInfo = new UserInfo(id: 1, description: "a description")

        im.setFullyIdentified "test", userInfo

        shouldFail(IllegalArgumentException) {
            im.setFullyIdentified null, userInfo
        }
        shouldFail(IllegalArgumentException) {
            im.setFullyIdentified "", userInfo
        }
        shouldFail(IllegalArgumentException) {
            im.setFullyIdentified " \t ", userInfo
        }
        shouldFail(IllegalArgumentException) {
            im.setFullyIdentified "test", null
        }

        im.setFullyIdentified "test", userInfo

        assert ! im.isAnonymous()
        assert ! im.isPartiallyIdentified()
        assert im.isFullyIdentified()

        assert im.getUserId() == 1
        assert im.getUserName() == "test"
        assert im.getUserInfo() == userInfo
    }

    /**
     * Preferences include neither an url nor a user name => we have
     * an anonymous user
     */
    @Test
    public void initFromPreferences_1() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        // reset it
        im.@userName = null
        im.@userInfo = null

        Main.pref.put "osm-server.url", null
        Main.pref.put "osm-server.username", null

        im.initFromPreferences()

        assert im.isAnonymous()
    }

    /**
     * Preferences include neither an url nor a user name => we have
     * an annoymous user
     */
    @Test
    public void initFromPreferences_2() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        // reset it
        im.@userName = null
        im.@userInfo = null

        // for this test we disable the listener
        Main.pref.removePreferenceChangeListener im

        Main.pref.put "osm-server.url", "http://api.openstreetmap.org"
        Main.pref.put "osm-server.username", null

        im.initFromPreferences()

        assert im.isAnonymous()
    }

    /**
     * Preferences include an user name => we have a partially identified user
     */
    @Test
    public void initFromPreferences_3() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        // for this test we disable the listener
        Main.pref.removePreferenceChangeListener im

        // reset it
        im.@userName = null
        im.@userInfo = null

        Main.pref.put "osm-server.url", "http://api.openstreetmap.org"
        Main.pref.put "osm-server.username", "test"

        im.initFromPreferences()

        assert im.isPartiallyIdentified()
    }

    /**
     * Preferences include an user name which is different from the current
     * user name and we are currently fully identifed => josm user becomes
     * partially identified
     */
    @Test
    public void initFromPreferences_4() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        // for this test we disable the listener
        Main.pref.removePreferenceChangeListener im

        im.setFullyIdentified "test1", new UserInfo(id: 1)

        Main.pref.put "osm-server.url", "http://api.openstreetmap.org"
        Main.pref.put "osm-server.username", "test2"

        im.initFromPreferences()

        assert im.isPartiallyIdentified()
    }

    /**
     * Preferences include an user name which is the same as the current
     * user name and we are currently fully identifed => josm user remains
     * fully identified
     */
    @Test
    public void initFromPreferences_5() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        // for this test we disable the listener
        Main.pref.removePreferenceChangeListener im

        im.setFullyIdentified "test1", new UserInfo(id: 1)

        Main.pref.put "osm-server.url", "http://api.openstreetmap.org"
        Main.pref.put "osm-server.username", "test1"

        im.initFromPreferences()

        assert im.isFullyIdentified()
    }

    @Test
    public void apiUrlChanged() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        // make sure im is a preference change listener
        Main.pref.addPreferenceChangeListener im

        // reset it
        im.@userName = null
        im.@userInfo = null

        Main.pref.put "osm-server.url", "http://api.openstreetmap.org"
        assert im.isAnonymous()

         Main.pref.put "osm-server.url", null
         assert im.isAnonymous()

        // reset it
        im.@userName = "test"
        im.@userInfo = null

        Main.pref.put "osm-server.url", "http://api.openstreetmap.org"
        assert im.isPartiallyIdentified()
        assert im.getUserName() == "test"

        Main.pref.put "osm-server.url", null
        assert im.isAnonymous()

        // reset it
        im.@userName = "test"
        im.@userInfo = new UserInfo(id:1)

        Main.pref.put "osm-server.url", "http://api.openstreetmap.org"
        assert im.isPartiallyIdentified()
        assert im.getUserName() == "test"

        // reset it
        im.@userName = "test"
        im.@userInfo = new UserInfo(id:1)


        Main.pref.put "osm-server.url", null
        assert im.isAnonymous()
    }

    @Test
    public void userNameChanged() {
        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance()

        // make sure im is a preference change listener
        Main.pref.addPreferenceChangeListener im

        // reset it
        im.@userName = null
        im.@userInfo = null

        Main.pref.put "osm-server.username", "test"
        assert im.isPartiallyIdentified()
        assert im.getUserName() == "test"

        Main.pref.put "osm-server.username", null
        assert im.isAnonymous()

        // reset it
        im.@userName = "test1"
        im.@userInfo = null

        Main.pref.put "osm-server.username", "test2"
        assert im.isPartiallyIdentified()
        assert im.getUserName() == "test2"

        Main.pref.put "osm-server.username", null
        assert im.isAnonymous()

        // reset it
        im.@userName = "test1"
        im.@userInfo = new UserInfo(id:1)

        Main.pref.put "osm-server.username", "test2"
        assert im.isPartiallyIdentified()
        assert im.getUserName() == "test2"

        // reset it
        im.@userName = "test1"
        im.@userInfo = new UserInfo(id:1)


        Main.pref.put "osm-server.username", null
        assert im.isAnonymous()
    }
}
