/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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
 *
 *      http://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.
 */

/*global ok: true, start: true, test: true, equal: true, deepEqual: true,
 QUnit: true, expect: true, stop: true */

jQuery(document).ready(function() {
	"use strict";

	const { test } = QUnit;

	QUnit.module('Wicket.ChannelManager', function() {

	/**
	 * Tests queueing channel.
	 * For 0 to 9 adds callback functions that just appends the current value of
	 * the counter to the 'result'.
	 * Verifies that the final result contains all values of the counter.
	 */
	test('queue', assert => {
		const done = assert.async();
		assert.expect(1);
		stop();

		var cm		= new Wicket.ChannelManager(),
			ch		= 'name|s',
			i		= 0,
			result	= '',
			iterations = 10,
			toExecute = function (j) {
				return function() {
					window.setTimeout(function() {
						result += j;
						cm.done(ch);

						if (j === iterations - 1) {
							assert.equal(result, '0123456789');
							done();
						}
					}, 1);
				};
			};

		for (; i < iterations; i++) {
			cm.schedule(ch, toExecute(i));
		}
	});

	/**
	 * Tests 'drop' channel.
	 * For 0 to 9 adds callback functions to the queueing channel. Only for the
	 * value of 5 adds a callback function to the drop channel.
	 * The execution starts with 0 but the DROP callback (for 5) drops the callbacks for
	 * 1, 2, 3 and 4, so they are missed. '5' registers a '!drop!' and then all following
	 * queueing callbacks are executed.
	 * The final result must be "0!drop!6789"
	 * - 0 for the first queueing callback
	 * - !drop! for the 5th
	 * - 6, 7, 8 and 9
	 */
	test('drop', assert => {
		const done = assert.async();
		assert.expect(1);

		// stop();

		var cm		= new Wicket.ChannelManager(),	// the manager
			name	= 'name',						// the channel's name
			chq		= name + '|s',					// the channel(s) to queue
			chd		= name + '|d',					// the channel to drop
			number	= 10,							// the number of channels to schedule
			i		= 0,							// the current iteration
			result	= '',							// the container for the actual result
			queueCallback = function(k) {
				result += k;
				cm.done(chq);

				if (k === (number - 1)) {
					assert.equal(result, '0!drop!6789');
					done();
				}
			},
			toExecuteQueued = function (y) {
				return function() {
					window.setTimeout(function() {queueCallback(y);}, 1);
				};
			},
			toExecuteDropped = function() {
				result += '!drop!';
				cm.done(chd);
			};

		for (; i < number; i++) {

			cm.schedule(chq, toExecuteQueued(i));

			if (i === (number / 2)) {
				cm.schedule(chd, toExecuteDropped);
			}
		}
	});

	/**
	 * Tests 'active' channel type.
	 * Schedules one long running request and 10 normal ones after it.
	 * All 10 normal ones should be discarded.
	 */
	test('active', assert => {
		const done = assert.async();
		assert.expect(1);

		stop();

		var cm      = new Wicket.ChannelManager(),	// the manager
			name    = 'name',						// the channel's name
			cha     = name + '|a',					// the active channel
			number  = 10,							// the number of requests to schedule while the active request is still running
			i       = 0,							// the current iteration
			queueCallback = function() {

				// run in a timeout to simulate long running request
				setTimeout(function() {
					assert.ok(true, "The initial request is executed!");

					// mark the channel non-busy
					cm.done(cha);
					done();
				}, 100);
			},
			toExecute = function () {
				assert.ok(false, "Requests in the active channel should not be executed.");
			};

		// schedule the long running callback (the active one)
		cm.schedule(cha, queueCallback);

		// try to schedule more requests
		// they will be disacarded because the channel is busy
		for (; i < number; i++) {
			cm.schedule(cha, toExecute);
		}

	});

	/**
	 * Asserts that the ChannelManager removes entries for done()-ed channels
	 */
	test('clean up', assert => {
		const done = assert.async();
		assert.expect(11);

		stop();

		var cm      = Wicket.channelManager,		// the manager
			name    = 'name',						// the channel name
			cha     = name + '|s',					// the channel
			number  = 10,							// the number of requests to schedule while the active request is still running
			i       = 0,							// the current iteration
			callback = function() {
				window.setTimeout(function() {
					cm.done(cha);
				}, 0);
			};

		for (; i < number; i++) {
			cm.schedule(cha, callback);
			assert.ok(cm.channels[name], "A channel exists.");
		}

		window.setTimeout(function() {
			assert.equal(undefined, cm.channels[name], "The channel should not be in the manager anymore");
			done();
		}, 500);
	});
	
	});
});
