/*
 * #%L
 * Wikidata Toolkit Wikibase API
 * %%
 * Copyright (C) 2014 - 2015 Wikidata Toolkit Developers
 * %%
 * 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
 * 
 *      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.
 * #L%
 */

package org.wikidata.wdtk.wikibaseapi;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.junit.jupiter.api.Test;
import org.wikidata.wdtk.datamodel.helpers.Datamodel;
import org.wikidata.wdtk.util.CompressionType;
import org.wikidata.wdtk.wikibaseapi.apierrors.MaxlagErrorException;
import org.wikidata.wdtk.wikibaseapi.apierrors.MediaWikiApiErrorException;
import org.wikidata.wdtk.wikibaseapi.apierrors.TokenErrorException;

public class WbEditingActionTest {

	@Test
	public void testOffineErrors() throws IOException,
			MediaWikiApiErrorException {
		MockBasicApiConnection con = new MockBasicApiConnection();
		WbEditingAction weea = new WbEditingAction(con,
				Datamodel.SITE_WIKIDATA);

		assertThrows(IOException.class, () -> weea.wbEditEntity("Q42", null, null, null,
				"{}", true, false, 0, null, null));
	}

	@Test
	public void testApiErrorGettingToken() throws IOException,
			MediaWikiApiErrorException {
		MockBasicApiConnection con = new MockBasicApiConnection();
		Map<String, String> params = new HashMap<>();
		params.put("action", "query");
		params.put("meta", "tokens");
		params.put("type", "csrf");
		params.put("format", "json");
		// This error makes no sense for this action, but that does not matter
		// here:
		con.setWebResourceFromPath(params, this.getClass(),
				"/error-badtoken.json", CompressionType.NONE);

		params.clear();
		params.put("action", "wbeditentity");
		params.put("id", "Q42");
		params.put("token", null);
		params.put("format", "json");
		params.put("data", "{}");
		params.put("maxlag", "5");
		con.setWebResourceFromPath(params, this.getClass(),
				"/error-badtoken.json", CompressionType.NONE);

		WbEditingAction weea = new WbEditingAction(con,
				Datamodel.SITE_WIKIDATA);
		assertThrows(TokenErrorException.class, () -> weea.wbEditEntity("Q42", null, null, null, "{}", false, false, 0, null, null));
	}

	@Test
	public void testNoTokenInReponse() throws IOException,
			MediaWikiApiErrorException {
		MockBasicApiConnection con = new MockBasicApiConnection();
		Map<String, String> params = new HashMap<>();
		params.put("action", "query");
		params.put("meta", "tokens");
		params.put("format", "json");
		params.put("type", "csrf");
		// This error makes no sense for this action, but that does not matter
		// here:
		con.setWebResource(params, "{}");

		params.clear();
		params.put("action", "wbeditentity");
		params.put("id", "Q42");
		params.put("token", null);
		params.put("format", "json");
		params.put("data", "{}");
		params.put("maxlag", "5");
		con.setWebResourceFromPath(params, this.getClass(),
				"/error-badtoken.json", CompressionType.NONE);

		WbEditingAction weea = new WbEditingAction(con,
				Datamodel.SITE_WIKIDATA);

		assertThrows(TokenErrorException.class, () -> weea.wbEditEntity("Q42", null, null, null, "{}", false, false, 0, null, null));
	}

	@Test
	public void testApiErrorMaxLag() throws IOException,
			MediaWikiApiErrorException {
		MockBasicApiConnection con = new MockBasicApiConnection();
		Map<String, String> params = new HashMap<>();
		params.put("action", "query");
		params.put("meta", "tokens");
		params.put("type", "csrf");
		params.put("format", "json");
		con.setWebResourceFromPath(params, this.getClass(),
				"/query-csrf-token-loggedin-response.json",
				CompressionType.NONE);

		params.clear();
		params.put("action", "wbeditentity");
		params.put("id", "Q42");
		params.put("token", "42307b93c79b0cb558d2dfb4c3c92e0955e06041+\\");
		params.put("format", "json");
		params.put("data", "{}");
		params.put("maxlag", "5");
		con.setWebResourceFromPath(params, this.getClass(),
				"/error-maxlag.json", CompressionType.NONE);

		WbEditingAction weea = new WbEditingAction(con,
				Datamodel.SITE_WIKIDATA);
		weea.setMaxLagFirstWaitTime(0); // speed up the test ...
		assertThrows(MaxlagErrorException.class, () -> weea.wbEditEntity("Q42", null, null, null, "{}", false, false, 0, null, null));
	}

	@Test
	public void testIdAndSite() throws IOException, MediaWikiApiErrorException {
		WbEditingAction weea = new WbEditingAction(
				new MockBasicApiConnection(), Datamodel.SITE_WIKIDATA);
		assertThrows(IllegalArgumentException.class, () -> weea.wbEditEntity("Q1234", "enwiki", null, null, "{}", false, false, 0,
				null, null));
	}

	@Test
	public void testIdAndTitle() throws IOException, MediaWikiApiErrorException {
		WbEditingAction weea = new WbEditingAction(
				new MockBasicApiConnection(), Datamodel.SITE_WIKIDATA);
		assertThrows(IllegalArgumentException.class, () -> weea.wbEditEntity("Q1234", null, "Title", null, "{}", false, false, 0,
				null, null));
	}

	@Test
	public void testTitleNoSite() throws IOException,
			MediaWikiApiErrorException {
		WbEditingAction weea = new WbEditingAction(
				new MockBasicApiConnection(), Datamodel.SITE_WIKIDATA);
		assertThrows(IllegalArgumentException.class, () -> weea.wbEditEntity(null, null, "Title", null, "{}", false, false, 0,
				null, null));
	}

	@Test
	public void testNewAndId() throws IOException, MediaWikiApiErrorException {
		WbEditingAction weea = new WbEditingAction(
				new MockBasicApiConnection(), Datamodel.SITE_WIKIDATA);
		assertThrows(IllegalArgumentException.class, () -> weea.wbEditEntity("Q1234", null, null, "item", "{}", false, false, 0,
				null, null));
	}

	@Test
	public void testNewAndSite() throws IOException, MediaWikiApiErrorException {
		WbEditingAction weea = new WbEditingAction(
				new MockBasicApiConnection(), Datamodel.SITE_WIKIDATA);
		assertThrows(IllegalArgumentException.class, () -> weea.wbEditEntity(null, "enwiki", null, "item", "{}", false, false, 0,
				null, null));
	}

	@Test
	public void testNewAndTitle() throws IOException,
			MediaWikiApiErrorException {
		WbEditingAction weea = new WbEditingAction(
				new MockBasicApiConnection(), Datamodel.SITE_WIKIDATA);
		assertThrows(IllegalArgumentException.class, () -> weea.wbEditEntity(null, null, "Title", "item", "{}", false, false, 0,
				null, null));
	}

	@Test
	public void testNoTask() throws IOException, MediaWikiApiErrorException {
		WbEditingAction weea = new WbEditingAction(
				new MockBasicApiConnection(), Datamodel.SITE_WIKIDATA);
		assertThrows(IllegalArgumentException.class, () -> weea.wbEditEntity(null, null, null, null, "{}", false, false, 0, null, null));
	}
	
	@Test
	public void testGetLag() throws IOException, MediaWikiApiErrorException {
		MockBasicApiConnection con = new MockBasicApiConnection();
		Map<String, String> params = new HashMap<>();
		params.put("action", "query");
		params.put("maxlag", "-1");
		params.put("format", "json");
		con.setWebResourceFromPath(params, this.getClass(),
				"/error-maxlag-full.json",
				CompressionType.NONE);
		
		WbEditingAction weea = new WbEditingAction(
				con, Datamodel.SITE_WIKIDATA);
		double lag = weea.getCurrentLag();
		assertEquals(3.45, lag, 0.001);
	}

}
