package info.bukova.isspst.services.dbinfo;

import info.bukova.isspst.Constants;
import info.bukova.isspst.data.DbInfo;
import info.bukova.isspst.services.AbstractService;
import org.hibernate.SQLQuery;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

public class DbInfoServiceImpl extends AbstractService<DbInfo> implements DbInfoService
{
	private DbInfo getDbInfo()
	{
		DbInfo dbInfo = null;

		List<DbInfo> list = this.getAll();

		if (list.isEmpty())
		{
			dbInfo = new DbInfo();
			this.add(dbInfo);
			list = this.getAll();
		}

		for (DbInfo item : list)
		{
			dbInfo = item;
			break;
		}

		return dbInfo;
	}

	@Override
	@Transactional
	public void changeDatabase()
	{
		class Str2Str
		{
			private String key;
			private String value;

			public Str2Str(String key, String value)
			{
				this.key = key;
				this.value = value;
			}

			public String getKey()
			{
				return this.key;
			}

			public String getValue()
			{
				return this.value;
			}
		}

		// String source = UserCountUtils.encryptUserCount(1000);
		// long users = UserCountUtils.decryptUserCount(source);

		long dbVersion = this.getDbInfo().getVersion();

		if (Constants.DB_VERSION > dbVersion)
		{
			SQLQuery sq = null;
			String sql = "";

			if (dbVersion < 1)
			{
				List<Str2Str> tables = new ArrayList<Str2Str>();

				tables.add(new Str2Str("ADDRESS", "DESCRIPTION"));
				tables.add(new Str2Str("BUILDING", "DESCRIPTION"));
				tables.add(new Str2Str("MATERIAL", "DESCRIPTION"));
				tables.add(new Str2Str("MUNIT", "DESCRIPTION"));
				tables.add(new Str2Str("ORDERS", "DESCRIPTION"));
				tables.add(new Str2Str("ORDER_ITEM", "DESCRIPTION"));
				tables.add(new Str2Str("PERMISSION", "DESCRIPTION"));
				tables.add(new Str2Str("REQUIREMENT", "DESCRIPTION"));
				tables.add(new Str2Str("REQUIREMENTTYPE", "DESCRIPTION"));
				tables.add(new Str2Str("REQUIREMENT_ITEMS", "DESCRIPTION"));
				tables.add(new Str2Str("ROLE", "DESCRIPTION"));
				tables.add(new Str2Str("SERVICE", "DESCRIPTION"));
				tables.add(new Str2Str("TRIPREQUIREMENT", "DESCRIPTION"));

				tables.add(new Str2Str("MATERIAL", "MUNIT_DESCRIPTION"));
				tables.add(new Str2Str("ORDERS", "INVOICE_DESCRIPTION"));
				tables.add(new Str2Str("ORDERS", "DELIVERY_DESCRIPTION"));
				tables.add(new Str2Str("ORDERS", "SUPPLIER_DESCRIPTION"));
				tables.add(new Str2Str("ORDER_ITEM", "MUNIT_DESCRIPTION"));
				tables.add(new Str2Str("REQUIREMENT_ITEMS", "MUNIT_DESCRIPTION"));
				tables.add(new Str2Str("TRIPREQUIREMENT", "VEHICLE_DESCRIPTION"));
				tables.add(new Str2Str("TRIP_BILL_ITEMS", "BACK_VEHICLE_DESCRIPTION"));
				tables.add(new Str2Str("TRIP_BILL_ITEMS", "VEHICLE_DESCRIPTION"));

				for (Str2Str item : tables)
				{
					sql = "ALTER TABLE " + item.getKey() + " MODIFY " + item.getValue() + " VARCHAR(" + String.valueOf(Constants.LEN_DESCRIPTION) + ")";
					sq = this.dao.getSession().createSQLQuery(sql);
					sq.executeUpdate();
				}
			}

			if (dbVersion < 2)
			{
				List<String> tables = new ArrayList<String>();

				tables.add("MATERIAL");
				tables.add("ORDER_ITEM");
				tables.add("REQUIREMENT_ITEMS");
				
				for (String item : tables)
				{
					sql = "UPDATE " + item + " SET MUNIT_ID = 0 WHERE (MUNIT_ID Is NULL) ";
					sq = this.dao.getSession().createSQLQuery(sql);
					sq.executeUpdate();
				}
			}

			if (dbVersion < 3)
			{
				sql = "UPDATE INVOICING SET COMPLETED = false WHERE (COMPLETED Is NULL) ";
				sq = this.dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
			}

			if (dbVersion < 4)
			{
				sql = "UPDATE TRIP_BILL SET RESULT_MESSAGE = 'Zpráva z pracovní cesty' WHERE (RESULT_MESSAGE Is NULL) ";
				sq = this.dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
			}

			if (dbVersion < 5) {
				sql = "ALTER TABLE TRIP_BILL MODIFY RESULT_MESSAGE VARCHAR(" + String.valueOf(Constants.LEN_RESULT_MESSAGE) + ")";
				sq = this.dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
			}

			if (dbVersion > 0 && dbVersion < 6) {
				sql = "INSERT INTO SEASON(DESCRIPTION, VALID_FROM, VALID_TO, ACTIVE) " +
						"VALUES ('2015', '2015-01-01', '2015-12-31', 0)";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				sql = "INSERT INTO SEASON(DESCRIPTION, VALID_FROM, VALID_TO, ACTIVE) " +
						"VALUES ('2016', '2016-01-01', NULL, 1)";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				sql = "UPDATE NUMBERSERIES SET SEASON_ID = 2";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				sql = "INSERT INTO NUMBERSERIES(MODULE, PREFIX, NUMBER, SEASON_ID) " +
						"VALUES ('REQUIREMENTS', 'P', 2528, 1)";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				sql = "INSERT INTO NUMBERSERIES(MODULE, PREFIX, NUMBER, SEASON_ID) " +
						"VALUES ('ORDER', 'OBJ', 55, 1)";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				// rozdeleni dat do sezon
				sql = "UPDATE REQUIREMENT SET SEASON_ID = 2 WHERE NUMSER LIKE 'P16%'";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
				sql = "UPDATE REQUIREMENT SET SEASON_ID = 1 WHERE NUMSER LIKE 'P0%'";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				sql = "UPDATE TRIPREQUIREMENT SET SEASON_ID = 2 WHERE NUMSER LIKE 'P16%'";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
				sql = "UPDATE TRIPREQUIREMENT SET SEASON_ID = 1 WHERE NUMSER LIKE 'P0%'";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				sql = "UPDATE ORDERS SET SEASON_ID = 2 WHERE NUMSER LIKE 'OBJ16%'";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
				sql = "UPDATE ORDERS SET SEASON_ID = 1 WHERE NUMSER LIKE 'OBJ0%'";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				sql = "UPDATE TRIP_BILL_APPROVAL SET SEASON_ID = 2 " +
						" WHERE TRIPBILL_ID in " +
						"       (SELECT tb.ID FROM TRIP_BILL AS tb " +
						"         JOIN TRIPREQUIREMENT ON TRIPREQUIREMENT.ID = tb.REQUIREMENT_ID WHERE NUMSER LIKE 'P16%')";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
				sql = "UPDATE TRIP_BILL_APPROVAL SET SEASON_ID = 1 " +
						"WHERE TRIPBILL_ID in " +
						"(SELECT tb.ID FROM TRIP_BILL AS tb " +
						"JOIN TRIPREQUIREMENT ON TRIPREQUIREMENT.ID = tb.REQUIREMENT_ID WHERE NUMSER LIKE 'P0%')";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();

				sql = "UPDATE TRIP_BILL tb JOIN TRIPREQUIREMENT ON TRIPREQUIREMENT.ID = tb.REQUIREMENT_ID " +
						"SET tb.SEASON_ID = 2 WHERE NUMSER LIKE 'P16%'";
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
				sql = "UPDATE TRIP_BILL tb JOIN TRIPREQUIREMENT ON TRIPREQUIREMENT.ID = tb.REQUIREMENT_ID " +
						"SET tb.SEASON_ID = 1 WHERE NUMSER LIKE 'P0%'";;
				sq = dao.getSession().createSQLQuery(sql);
				sq.executeUpdate();
			}

			this.updateDatabaseVersion();
		}
	}

	@Override
	@Transactional
	public void updateDatabaseVersion()
	{
		DbInfo dbInfo = this.getDbInfo();
		dbInfo.setVersion(Constants.DB_VERSION);
		this.update(dbInfo);
	}
}
