package com.sharefaith.thesharefaithapp.base;

/**
 * Created by costmo on 2014-10-21.
 * class for holding configuration data
 */

import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.graphics.Point;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;

import com.appideas.base.AiDb;
import com.appideas.base.AiSTr;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;

public class SFConfig
{
	/**
	 * The database abstraction
	 */
	public AiDb mDb;

	/**
	 * Time of last sync
	 */
	public int mLastSync;

	/**
	 * The current schema version
	 */
	public int mSchemaVersion;

	/**
	 * Data in the sync queue
	 */
	public String mSyncData;

	/**
	 * The current theme
	 */
	public String mTheme;

	/**
	 * Currently unused icon weight (thickness)
	 */
	public String mWeight;

	/**
	 * The user's device class (phone or tablet)
	 */
	public String mDevice;

	/**
	 * The type of navigation for the current theme
	 */
	public String mNavType;

	/**
	 * The title bar string
	 */
	public String mAppTitle;

	/**
	 * The navigation/title bar color
	 */
	public String mNavColor;

	/**
	 * Path to the church's custom uploaded asset location (cache)
	 */
	public String mCustomAssetPath;

	/**
	 * Path to user media downloads
	 */
	public String mMediaAssetPath;

	/**
	 * Path to user media downloads
	 */
	public String mDbUpdatesPath;

	/**
	 * Path to user app files
	 */
	public String mAppFilesPath;

	/**
	 * Path to the current theme's asset files
	 */
	public String mThemeAssetPath;

	public String mTag = "Class_SFConfig";

	private final String FONTOFFSETSQL = "SELECT lookup_key, lookup_value FROM config_lookup WHERE lookup_key = 'fontsize'";

	public boolean demoIdsRearranged;


	/**
	 * Class constructor
	 *
	 * @since		20141021
	 */
	public SFConfig()
	{
		this.mDb = SFApplication.getInstance().getDb();
		this.populateMembers();
	}

	/**
	 * Populates member variables with values from the data source
	 *
	 * @since		20141021
	 * @author		costmo
	 */
	public void populateMembers()
	{
		this.mLastSync = 0;
		this.mSyncData = "";
		this.mTheme = "";
		this.mWeight = "";
		this.mAppTitle = "";
		this.mNavColor = "";

		this.demoIdsRearranged = false;

		this.mSchemaVersion = this.mDb.mDataVersion;
		this.mDevice = this.getDeviceClass();
		this.mNavType = this.getNavTypeForTheme( this.mTheme );

		this.mThemeAssetPath = "";
		this.mCustomAssetPath = this.mDb.mContext.getFilesDir() + "/appfiles/custom/";
		this.mMediaAssetPath = this.mDb.mContext.getFilesDir() + "/appfiles/media/";
		this.mAppFilesPath = "/appfiles/";

		this.mDbUpdatesPath = "/appfiles/dbupdates/";

		// set font sizes for the app
		// we can't call SFConfig.isTablet() or this.defaultFontSize() here due to recursion

		String sql = "SELECT lookup_key, lookup_value FROM config_lookup";

		String[][] result = this.mDb.query( sql );
		for( int i = 0; i < result.length; i++ )
		{
			String key = AiSTr.denullifyString( result[i][0] );

			if( key.equals( "last_sync" ) )
			{
				this.mLastSync =  AiSTr.denullifyInt( result[i][1] );
			}
			else if( key.equals( "sync_data" ) )
			{
				this.mSyncData =  AiSTr.denullifyString( result[ i ][ 1 ] );
			}
			else if( key.equals( "theme" ) )
			{
				this.mTheme =  AiSTr.denullifyString( result[i][1] );
				this.mThemeAssetPath = this.mDb.mContext.getFilesDir() + "/appfiles/themes/" + this.mTheme + "/";
			}
			else if( key.equals( "weight" ) )
			{
				this.mWeight=  AiSTr.denullifyString( result[i][1] );
			}
			else if( key.equals( "apptitle" ) )
			{
				this.mAppTitle=  AiSTr.denullifyString( result[i][1] );
			}
			else if( key.equals( "navcolor" ) )
			{
				this.mNavColor=  AiSTr.denullifyString( result[i][1] );
			}
			else if( key.equals( "demoidsrearranged" ) )
			{
				this.demoIdsRearranged=  AiDb.fixBoolean( AiSTr.denullifyInt( result[i][1] ) );
			}

		} // for( int i = 0; i < result.length; i++ )

		if( this.mNavColor == null || this.mNavColor.length() < 1 )
		{
			this.mNavColor = "39589a";
		}

	} // populateMembers

	/**
	 * Gets the navigation type for the given theme
	 *
	 * @since		20141021
	 * @author		costmo
	 */
	public String getNavTypeForTheme( String theme )
	{
		String leftThemes[] = { "inspire" };

		if( Arrays.asList( leftThemes ).contains( theme ) )
		{
			return "left";
		}

		return "bottom";
	}

	/**
	 * Gets the type of device
	 *
	 * @since		20141021
	 * @author		costmo
	 */
	public String getDeviceClass()
	{
		WindowManager wm = (WindowManager) this.mDb.mContext.getSystemService( Context.WINDOW_SERVICE );
		Display display = wm.getDefaultDisplay();
		Point size = new Point();
		display.getSize( size );
		int width = size.x;
		int height = size.y;

		if( width >= 1024 || height >= 1024 )
		{
			return "tablet";
		}

		return "phone";
	}

	/**
	 * This is probably more accurate/future-proof than getDeviceClass()
	 * @return boolean true if tablet, false if not. (Return nothing if iPad)
	 */
	public static boolean isTablet()
	{
		SFConfig config = new SFConfig();
		return(	config.mDb.mContext.getResources().getConfiguration().screenLayout
				& Configuration.SCREENLAYOUT_SIZE_MASK )
				>= Configuration.SCREENLAYOUT_SIZE_LARGE;
	}

	public String toString()
	{

		return	"Last sync: " + this.mLastSync + "; " +
				"Schema version: " + this.mSchemaVersion + "; " +
				"Sync data: " + this.mSyncData + "; " +
				"Theme: " + this.mTheme + "; " +
				"Weight: " + this.mWeight + "; " +
				"Device: " + this.mDevice + "; " +
				"Nav type: " + this.mNavType + "; " +
				"App title: " + this.mAppTitle + "; " +
				"Nav color: " + this.mNavColor + "; " +
				"Theme path: " + this.mThemeAssetPath + "; " +
				"Custom path: " + this.mCustomAssetPath + "; " +
				"Media path: " + this.mMediaAssetPath + "; " +
				"Appfiles path: " + this.mAppFilesPath + ";" ;
	}

	public static void databaseFileSync()
	{
		SFConfig config = new SFConfig();

		Log.d( "Class_SFConfig", "Trying to make directory " + config.mDbUpdatesPath );
		File destination = new File( config.mDb.mContext.getFilesDir() +config.mDbUpdatesPath );
		if( destination.isDirectory() )
		{
			Log.d( "Class_SFConfig", "Directory already exists " );
		}
		boolean success = destination.mkdirs();
		if( success )
		{
			Log.d( "Class_SFConfig", "Created directory " + config.mDbUpdatesPath );
		}
		SFConfig.recursiveAssetCopy( config.mDb.mContext, "appfiles/dbupdates" );
	}

	/**
	 * Do initial setup, particularly of the files that need to be in specific places on the filesystem
	 *
	 * @since		20141021
	 * @author		costmo
	 */
	public static void initialConfig()
	{
		SFConfig config = new SFConfig();

		String directories[] = {
				config.mDb.mContext.getFilesDir() + "/appfiles",
				config.mThemeAssetPath,
				config.mCustomAssetPath,
				config.mMediaAssetPath,
				config.mDbUpdatesPath,
				config.mAppFilesPath
		};

		for( int i = 0; i < directories.length; i++ )
		{
			Log.d( "Class_SFConfig", "Trying to make directory " + directories[i] );
			File destination = new File( directories[i] );
			if( destination.isDirectory() )
			{
				Log.d( "Class_SFConfig", "Directory already exists " );
			}
			boolean success = destination.mkdirs();
			if( success )
			{
				Log.d( "Class_SFConfig", "Created directory " + directories[i] );
			}
		}

		// write our custom themes data to some place we can get to the files outside of assets
		SFConfig.recursiveAssetCopy( config.mDb.mContext, "appfiles/themes/" + config.mTheme );
		//uncomment these lines to also replicate some user-installed files
		//SFConfig.recursiveAssetCopy( config.mDb.mContext, "appfiles/custom" );
		//SFConfig.recursiveAssetCopy( config.mDb.mContext, "appfiles/media" );

	}

	/**
	 *
	 * @param context
	 * @param path
	 */
	public static void recursiveAssetCopy( Context context, String path )
	{
		AssetManager manager = context.getAssets();

		try
		{
			String[] contents = manager.list( path );

			if( contents.length < 1 )
			{
				SFConfig.assetFileCopy( context, path );
			}
			else
			{
				for( int i = 0; i < contents.length; i++ )
				{
					String[] subitems = manager.list( path + "/" + contents[ i ] );
					if( subitems.length > 0 )
					{
						// This is a directory
						// try to make a destination directory
						File outputFile = new File( context.getFilesDir() + "/" + path + "/" + contents[ i ] );
						outputFile.mkdirs();

						// recurse the contents
						for( int j = 0; j < subitems.length; j++ )
						{
							SFConfig.recursiveAssetCopy( context, path + "/" + contents[ i ] + "/" + subitems[ j ] );
						}
					}
					else
					{
						SFConfig.assetFileCopy( context, path + "/" + contents[ i ] );
					}


				}
			}
		}
		catch( Exception e )
		{
			//Log.d( "Config", "Exception 0: " + e.toString() );
		}
	}

	/**
	 *
	 * @param context
	 * @param path
	 */
	public static void assetFileCopy( Context context, String path )
	{
		File output = new File( context.getFilesDir() + "/" + path );
		AssetManager am = context.getAssets();
		try
		{
			InputStream in = am.open( path );
			OutputStream out = new FileOutputStream( output );

			byte[] buffer = new byte[1024];
			int read = in.read( buffer );
			while( read != -1 )
			{
				//Log.d( "Config", "Reading:" );
				out.write( buffer, 0, read );
				read = in.read( buffer );
			}
			out.close();
			in.close();
		}
		catch( IOException e )
		{
			//Log.d( "Config", "Exception1: " + e );
		}

		File testFile = new File( context.getFilesDir() + "/" + path );
		if( testFile.length() < 1 )
		{
			//Log.d( "Config", "Empty file after write: " + path );
		}
	}

	/**
	 *
	 * @return
	 */
	public String customFontColorForNavColor()
	{
		if( this.mNavColor.equals( "000000" ) )
		{
			return "ffffff";
		}

		int color = (int)Long.parseLong( this.mNavColor, 16);
		double r = ((color >> 16) & 0xFF)/255.0;
		double g = ((color >> 8) & 0xFF)/255.0;
		double b = ((color >> 0) & 0xFF)/255.0;

		double finalDiff = 0.0;
		double biggest = r;
		biggest = (g > biggest) ? g : biggest;
		biggest = (b > biggest) ? b : biggest;

		if( biggest > 0.75 && biggest < 1.0 )
		{
			finalDiff = (1.0 - biggest);
		}
		else
		{
			finalDiff = (1.0 - biggest)/2;
		}

		r = r + finalDiff;
		g = g + finalDiff;
		b = b + finalDiff;

		int fixedR = (int)Math.floor( r * 255 );
		int fixedG = (int)Math.floor( g * 255 );
		int fixedB = (int)Math.floor( b * 255 );

		return Integer.toHexString( fixedR ) + Integer.toHexString( fixedG ) +Integer.toHexString( fixedB );
	}
}
