package kz.istt.locust;

//import android.content.Context;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import com.google.android.material.textfield.TextInputEditText;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import dbfields.DateInput;
import dbfields.DateTimeTM;
import dbfields.DateTimeText;
import dbfields.SpinnerDB;
import dbfields.AutoCompleteTextViewDB;
import dbfields.StringDB;

/*
 * Соответствие GUI полей и полей базы данных
 * Для сохранения значений и для их загрузки из базы
*/

public class DBGUITable 
{
	private Context m_context;

	//private DbOpenHelper m_dboh;
	//Для списка полей
	private List<Object> m_listO;
	private List<String> m_listN; //Имена столбцов
	private String m_table;

	public DBGUITable(Context context, String table)
	{
		m_context = context;
		m_table = table;
		//m_dboh = dboh;

		m_listO = new ArrayList<Object>();
		m_listN = new ArrayList<String>();
	}

	/**
	 * Получить тип столбца из таблицы
	 * @param name
	 * @return
	 */
	public String getType(String name)
	{
		String type=null;
		//Считываем поля и их типы из таблицы
		DbOpenHelper dboh = new DbOpenHelper(m_context);
		SQLiteDatabase rdb = null;
		Cursor cursor = null;
		try {
			rdb = dboh.getReadableDatabase();
			cursor = rdb.rawQuery("PRAGMA table_info('" + m_table + "');", null);
			if (cursor.moveToFirst()) {
				do {
					if (Tools.getStringFromCursor(cursor, "name").equals(name.toLowerCase())) {
						type = Tools.getStringFromCursor(cursor, "type");
						break;
					}
				} while (cursor.moveToNext());
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(cursor != null) { cursor.close(); }
			if(rdb != null) { rdb.close(); }
		}
		dboh.close();

		if(type!=null){
			return type.toLowerCase().trim();
		}else{
			return null;
		}
	}

	//Проверить название полей в базе и название параметров и если есть различия то вывести в консоль
	public boolean validateField(ContentValues cv)
	{
		boolean result = true;
		DbOpenHelper dboh = new DbOpenHelper(m_context);
		SQLiteDatabase rdb = null;
		Cursor cursor = null;
		try {
			rdb = dboh.getReadableDatabase();
			cursor = rdb.rawQuery("PRAGMA table_info('"+m_table+"');",null);
			if(cursor.moveToFirst())
			{
				do{
					String name=Tools.getStringFromCursor(cursor,"name");
					boolean find=false;
					String value="";
					Set<Map.Entry<String, Object>> valueSet = cv.valueSet();
					for (Map.Entry<String, Object> entry : valueSet) {
						if(entry.getKey().equals(name)) {
							find = true;
							Object obj = entry.getValue();
							if(obj!=null)
								value = obj.toString()+" "+obj.getClass().toString()+" = "+Tools.getStringFromCursor(cursor,"type");
							else
								value="null";
							break;
						}
					}
					if(!find)
						Log.e("CCALM", "Validate field = " + name + " not find in CV");
					else
						Log.e("CCALM", "Validate field = " + name + " find in CV value = "+value);
				}while (cursor.moveToNext());
			}
		}catch(Exception e){
			e.printStackTrace();
		} finally {
			if(cursor != null) { cursor.close(); }
			if (rdb != null) { rdb.close(); }
		}
		dboh.close();

		return result;
	}


	/*
	 * Передаётся компонент и название поля таблицы
	*/
	public void add(Object component, String name)
	{
		m_listO.add(component);
		m_listN.add(name);
	}

	/**
	 * Найти компонент по имени поля базы
	 * @param fieldName
	 * @return
	 */
	public Object findComponent(String fieldName)
	{
		for(int i=0;i<m_listN.size();i++)
		{
			if(m_listN.get(i).equals(fieldName)) return m_listO.get(i);
		}
		return null;
	}

	/* Вставить либо обновить запись из GUI элементов
	 * */
	public String write()
	{
		ContentValues cv = new ContentValues();
		for(int i=0;i<m_listO.size();i++)
		{
			String field = m_listN.get(i);
			String value = getValue(m_listO.get(i));
//if(field.equals("risk_agricultural")) {
//	Object o = m_listO.get(i);
//	Log.e("CCALM", "NOT FIND field = " + field + " value = " + getValue(o));
//}
			String type = getType(field);
			if(type==null) {
				Log.e("CCALM", "NOT FIND field = " + m_listN.get(i) + " value = " + value);
				continue;
			}
			Log.e("CCALM", "field = " + m_listN.get(i) + " value = " + value + " type = " + type);
			
			if(type.equals("text"))
			{
				cv.put(field, value);
			}else
			if(type.equals("integer") || type.equals("boolean"))
			{
				Integer val=null;
				if(value!=null) {
					try {
						val = Integer.parseInt(value);
					} catch (NumberFormatException e) {
					}
				}
				cv.put(field, val);
			}else
			if(type.equals("double") || type.equals("float"))
			{
				Double val=null;
				if(value!=null) {
					try {
						val = Double.parseDouble(value);
					} catch (NumberFormatException e) {
					}
				}
				cv.put(field, val);
			}else
			{
				Log.e("CCALM", "type= " + type + " = " + value);
			}

		}
		cv.put("send", 0); //Ставим признак не отправленности чтоб запись отправилась по расписанию

		String uid=null;
		//Проверка нужно ли вставить либо обновить по id записи
		boolean b=false;
		DbOpenHelper dboh = new DbOpenHelper(m_context);

		if(cv.getAsString("uid")!=null)
		{
			uid=cv.getAsString("uid");
			String sql="select 1 from "+m_table+" where uid = '" + uid +"'";
			SQLiteDatabase rdb=null;
			Cursor cursor = null;
			try {
				rdb = dboh.getReadableDatabase();
				cursor = rdb.rawQuery(sql,null);
				b=cursor.moveToFirst();
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				if(cursor != null) { cursor.close(); }
				if(rdb!=null) rdb.close();
			}
		}


		if(!b) //Вставляем новую запись
		{
			uid = UUID.randomUUID().toString();//.replace("-", ""); удаляеть - для экономии места не нужно
			cv.put("uid", uid);

			validateField(cv);

			SQLiteDatabase wdb=null;
			try {
				wdb = dboh.getWritableDatabase();
				wdb.beginTransaction(); //Вроде как защита от многопоточности (для сервиса)
				wdb.insert(m_table, null, cv);
				wdb.setTransactionSuccessful();
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				if(wdb!=null) wdb.endTransaction();
				if(wdb!=null) wdb.close();
			}

		}else //Обновить запись
		{
			validateField(cv);

			SQLiteDatabase wdb=null;
			try {
				wdb = dboh.getWritableDatabase();
				wdb.beginTransaction(); //Вроде как защита от многопоточности (для сервиса)
				uid=cv.getAsString("uid");
				wdb.update(m_table, cv, "uid = ?", new String[] {uid});
				wdb.setTransactionSuccessful();
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				if(wdb!=null) wdb.endTransaction();
				if(wdb!=null) wdb.close();
			}

		}

		dboh.close(); //Можно и не закрывать, главное закрыть getWritableDatabase() и getReadableDatabase()
		return uid;
	}

	/** Прочитать значения в GUI поля из базы по id записи
	 */
	public void read(String uid)
	{
		if (uid != null) // Выборка данных для редактирования
		{
			DbOpenHelper dboh = new DbOpenHelper(m_context);

			String sql = "";
			sql = "select * from "+m_table+" where uid='" + uid + "'";

			SQLiteDatabase rdb=null;
			Cursor cursor = null;
			try {
				rdb = dboh.getReadableDatabase();
				cursor = rdb.rawQuery(sql, null);
				if (cursor.moveToFirst())
				{
					//перебираем столбцы и вставляем значения в поля
					for(int i=0;i<cursor.getColumnCount();i++)
					{
						Object obj=findComponent(cursor.getColumnName(i));
						if(obj!=null)
						{
							//if(cursor.getColumnName(i).equals("date")) {
							//	Log.e("CCALM", "1 field " + cursor.getColumnName(i) + " = " + cursor.getString(i) + " type= " + cursor.getType(i));
							//}

							if(cursor.getType(i)==Cursor.FIELD_TYPE_FLOAT){ //Because cutting double
								setValue(obj, ""+cursor.getDouble(i));
							}else {
								setValue(obj, cursor.getString(i));
							}

							//для проверки обратное действие
							//Log.e("CCALM", "read field = " + cursor.getColumnName(i) + " val1 = " + cursor.getString(i) + " val2 = " + getValue(findComponent(cursor.getColumnName(i))));
						}
					}
				}
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				if(cursor != null) { cursor.close(); }
				if(rdb != null) { rdb.close(); }
			}
			dboh.close();
		}

	}

	//Прочитать значение из GUI объекта "obj"
	public String getValue(Object obj)
	{
		String value = null;
		if(obj!=null)
		{
			String class_name = obj.getClass().toString();
			if(class_name.indexOf("android.widget.EditText")!=-1) value = ((EditText)obj).getText().toString(); else
			if(class_name.indexOf("android.material.textfield.TextInputEditText")!=-1) value = ((TextInputEditText)obj).getText().toString(); else
			if(class_name.indexOf("android.widget.Spinner")!=-1) value = ((Spinner)obj).getSelectedItem().toString(); else
			if(class_name.indexOf("android.widget.CheckBox")!=-1) value = ((CheckBox)obj).isChecked() ? "1" : "0"; else
			if(class_name.indexOf("java.lang.Integer")!=-1) value = ((Integer)obj).toString(); else
			if(class_name.indexOf("java.lang.String")!=-1) value = ((String)obj); else
			if(class_name.indexOf("dbfields.SpinnerDB")!=-1) value = ((SpinnerDB)obj).getValue(); else
			if(class_name.indexOf("dbfields.AutoCompleteTextViewDB")!=-1) value = ((AutoCompleteTextViewDB)obj).getValue(); else
			if(class_name.indexOf("dbfields.StringDB")!=-1) value = ((StringDB)obj).getValue(); else
			if(class_name.indexOf("dbfields.DateTimeTM")!=-1) value = ((DateTimeTM)obj).getValue(); else
			if(class_name.indexOf("dbfields.DateTimeText")!=-1) value = ((DateTimeText)obj).getValue(); else
			if(class_name.indexOf("dbfields.DateInput")!=-1)
			{
				if(((DateInput)obj).getDate()!=null)
					value = ((DateInput)obj).getDate().toString(); //В секундах
			}
		}
		if(value!=null && value.equals("")) value=null;
		return value;
	}

	//Установить значение "value" для GUI объекта "obj"
	public void setValue(Object obj, String value)
	{
		if(obj==null) return;
		String className = obj.getClass().toString();
		//Log.d("CCALM","getClass = "+className);

		if(className.indexOf("android.widget.EditText")!=-1) ((EditText)obj).setText(value);
		if(className.indexOf("android.material.textfield.TextInputEditText")!=-1) ((TextInputEditText)obj).setText(value);
		if(className.indexOf("android.widget.Spinner")!=-1) Tools.selSpinnerIC(((Spinner)obj), value);
		if(className.indexOf("android.widget.CheckBox")!=-1) ((CheckBox)obj).setChecked((value!=null && value.equals("1")) ? true : false);
		//if(className.indexOf("java.lang.Integer")!=-1) ((Integer)obj)=Integer.parseInt(value); так не работает
		//if(className.indexOf("java.lang.String")!=-1) ((String)obj)=value; так не работает
		if(className.indexOf("dbfields.SpinnerDB")!=-1) ((SpinnerDB)obj).setValue(value);
		if(className.indexOf("dbfields.AutoCompleteTextViewDB")!=-1) ((AutoCompleteTextViewDB)obj).setValue(value);
		if(className.indexOf("dbfields.StringDB")!=-1) ((StringDB)obj).setValue(value);
		if(className.indexOf("dbfields.DateTimeTM")!=-1) ((DateTimeTM)obj).setValue(value);
		if(className.indexOf("dbfields.DateTimeText")!=-1) ((DateTimeText)obj).setValue(value);
		if(className.indexOf("dbfields.DateInput")!=-1)
		{
			if(value==null)
			{	((DateInput)obj).setDate((Date)null);
			}
			else
			{	((DateInput)obj).setDate(Long.parseLong(value));
			}
		}
	}
}
