const string host_env = "FEEDBIN_TEST_HOST";
const string user_env = "FEEDBIN_TEST_USER";
const string password_env = "FEEDBIN_TEST_PASSWORD";

void delete_subscription(FeedbinAPI api, string url)
{
    var subscriptions = api.get_subscriptions();
    foreach(var subscription in subscriptions)
    {
        if(subscription.feed_url != url)
            continue;
        api.delete_subscription(subscription.id);
        break;
    }
}

void add_login_tests(string host)
{
    string? username = Environment.get_variable(user_env);
    string? password = Environment.get_variable(password_env);
    if(username == null || password == null)
		return;

	// Stick a random number at the end of Feed URL's to ensure that they're
	// unique, even if we run two tests against the same account
	uint nonce = Random.next_int();

    Test.add_data_func ("/feedbinapi/login", () => {

        var api = new FeedbinAPI(username, password, null, host);
        assert(api.login());

        api = new FeedbinAPI("wrong", "password", null, host);
        assert(!api.login());

        api.username = username;
        assert(!api.login());

        api.password = password;
        assert(api.login());
    });

    Test.add_data_func ("/feedbinapi/subscription", () => {
        if(username == null || password == null)
        {
            Test.skip(@"Need $user_env and $password_env set to run Feedbin tests");
            return;
        }

        var api = new FeedbinAPI(username, password, null, host);

        var url = "https://www.brendanlong.com/feeds/all.atom.xml?feedreader-test-subscribe-$(nonce)";
        delete_subscription(api, url);

        var subscription = api.add_subscription(url);
        assert(subscription.id != 0);

		{
			var got_subscription = api.get_subscription(subscription.id);
			assert(got_subscription.id == subscription.id);
		}

        bool found_subscription = false;
        foreach(var got_subscription in api.get_subscriptions())
        {
            if(got_subscription.id == subscription.id)
            {
				assert(got_subscription.feed_id == subscription.feed_id);
				assert(got_subscription.feed_url == subscription.feed_url);
				assert(got_subscription.site_url == subscription.site_url);
				assert(got_subscription.title == subscription.title);
                found_subscription = true;
            }
        }
        assert(found_subscription);

        string title = "Rename test";
        api.rename_subscription(subscription.id, title);
        var renamed_subscription = api.get_subscription(subscription.id);
        assert(renamed_subscription.title == title);

        api.delete_subscription(subscription.id);
        foreach(var got_subscription in api.get_subscriptions())
        {
            assert(got_subscription.id != subscription.id);
            assert(got_subscription.feed_url != url);
        }
    });

    Test.add_data_func ("/feedbinapi/taggings", () => {
        if(username == null || password == null)
        {
            Test.skip(@"Need $user_env and $password_env set to run Feedbin tests");
            return;
        }

        var api = new FeedbinAPI(username, password, null, host);

        var url = @"https://www.brendanlong.com/feeds/all.atom.xml?feedreader-test-taggings-$(nonce)";
        delete_subscription(api, url);

        var subscription = api.add_subscription(url);

        // The subscription is new so it shouldn't have any taggings
        var taggings = api.get_taggings();
        foreach(var tagging in taggings)
        {
            assert(tagging.feed_id != subscription.feed_id);
        }

        string category = "Taggings Test";
        api.add_tagging(subscription.feed_id, category);

        // Check taggings
        int64? tagging_id = null;
        foreach(var tagging in api.get_taggings())
        {
            if(tagging.feed_id == subscription.feed_id)
            {
                assert(tagging.name == category);
                tagging_id = tagging.id;
                break;
            }
        }
        assert(tagging_id != null);

        // Delete the tag and verify that it's gone
        api.delete_tagging(tagging_id);
        foreach(var tagging in api.get_taggings())
        {
            assert(tagging.feed_id != subscription.feed_id);
		}

		// cleanup
		api.delete_subscription(subscription.id);
    });

    Test.add_data_func ("/feedbinapi/entries", () => {
        if(username == null || password == null)
        {
            Test.skip(@"Need $user_env and $password_env set to run Feedbin tests");
            return;
        }

        var api = new FeedbinAPI(username, password, null, host);

		// Note: This one shouldn't be deleted or recreated, since we want the entries to be available
        var url = "https://www.brendanlong.com/feeds/all.atom.xml?feed-reader-test-entries";

        var subscription = api.add_subscription(url);

        /* FIXME: Figure out why this next line is failing
        var entries = api.get_entries(1, false, null, subscription.feed_id);
        foreach(var entry in entries)
        {
            assert(entry.feed_id == subscription.feed_id);
        }

		assert(entries.size > 0);
		int i = Random.int_range(0, entries.size);
        var entry = entries.to_array()[i];
        var entry_ids = new Gee.ArrayList<int64?>();
        entry_ids.add(entry.id);

        // read status
        api.set_entries_read(entry_ids, true);
        var unread_entries = api.get_unread_entries();
        assert(!unread_entries.contains(entry.id));

        api.set_entries_read(entry_ids, false);
        unread_entries = api.get_unread_entries();
        assert(unread_entries.contains(entry.id));

        api.set_entries_read(entry_ids, true);
        unread_entries = api.get_unread_entries();
        assert(!unread_entries.contains(entry.id));

        // starred status
        api.set_entries_starred(entry_ids, true);
        var starred_entries = api.get_starred_entries();
        assert(starred_entries.contains(entry.id));

        api.set_entries_starred(entry_ids, false);
        starred_entries = api.get_starred_entries();
        assert(!starred_entries.contains(entry.id));

        api.set_entries_starred(entry_ids, true);
        starred_entries = api.get_starred_entries();
        assert(starred_entries.contains(entry.id));
        */
    });

    Test.add_data_func ("/feedbinapi/favicons", () => {
        if(username == null || password == null)
        {
            Test.skip(@"Need $user_env and $password_env set to run Feedbin tests");
            return;
		}

        var api = new FeedbinAPI(username, password, null, host);

		// Note: This one shouldn't be deleted or recreated, since we want the entries to be available
        var url = "https://www.brendanlong.com/feeds/all.atom.xml?feed-reader-test-favicons";

		var subscription = api.add_subscription(url);
		var favicons = api.get_favicons();
		bool found_favicon = false;
		foreach(var i in favicons.entries)
		{
			if(i.key != "www.brendanlong.com")
				continue;
			// Don't check the contents of the Favicon because Feedbin doesn't
			// seem to neccessarily return the exact icon we gave it
			found_favicon = true;
			break;
		}
		// FIXME: We don't download icons on the test server because favicon downloading
		// is handled by a different service
		//assert(found_favicon);
	});
}

void main(string[] args)
{
	Test.init(ref args);

	string? host = Environment.get_variable(host_env);
	if(host == null)
		host = "https://api.feedbin.com";

    // Tests that don't need a login
    Test.add_data_func ("/feedbinapi/construct", () => {
        var api = new FeedbinAPI("user", "password", null, host);
        assert(api != null);
    });

    Test.add_data_func ("/feedbinapi/bad login", () => {
        var api = new FeedbinAPI("user", "password", null, host);

        assert(!api.login());
    });

    add_login_tests(host);

    Test.run ();
}
