package com.sharefaith.thesharefaithapp.base;

import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.text.Html;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;

import com.appideas.base.AiDb;
import com.appideas.base.AiSTr;
import com.sharefaith.thesharefaithapp.R;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Created by Sharefaith1 on 2014-10-30.
 */
public class SFUtil
{

	public SFUtil()
	{

	}

	public static Bitmap getResizedBitmap( Bitmap bm, int newWidth, int newHeight )
	{
		int width = bm.getWidth();
		int height = bm.getHeight();
		float scaleWidth = ((float) newWidth) / width;
		float scaleHeight = ((float) newHeight) / height;
		// CREATE A MATRIX FOR THE MANIPULATION
		Matrix matrix = new Matrix();
		// RESIZE THE BIT MAP
		matrix.postScale( scaleWidth, scaleHeight );

		// "RECREATE" THE NEW BITMAP
		Bitmap resizedBitmap = Bitmap.createBitmap( bm, 0, 0, width, height, matrix, false );
		return resizedBitmap;
	}

	public static DisplayMetrics displayMetrics()
	{
		SFApplication application = SFApplication.getInstance();

		DisplayMetrics metrics = new DisplayMetrics();
		application.getCurrentActivity().getWindowManager().getDefaultDisplay().getMetrics( metrics );


		Log.e( "METRICS", "D: " + metrics.density );
		Log.e( "METRICS", "D: " + metrics.densityDpi );
		Log.e( "METRICS", "M: " + metrics );


		return metrics;
	}


	public static int densityIdentifier()
	{
		return SFUtil.displayMetrics().densityDpi;
	}

	/*public static float getLeftOpenPosition()
	{
		if( SFUtil.densityIdentifier() >= DisplayMetrics.DENSITY_XXHIGH )
		{
			//Log.d("mTag","this is xxhigh_dpi");
			if(SFConfig.isTablet())
			{
				return  SFConstants.LEFT_OPEN_POSITION_XXHIGH_DPI *2;
			}
			return SFConstants.LEFT_OPEN_POSITION_XXHIGH_DPI;
		}
		else if( SFUtil.densityIdentifier() >= DisplayMetrics.DENSITY_XHIGH )
		{
			//Log.d("mTag","this is xhigh");
			if(SFConfig.isTablet())
			{
				return  SFConstants.LEFT_OPEN_POSITION *2;
			}
			return SFConstants.LEFT_OPEN_POSITION;
		}
		else
		{
			return SFConstants.LEFT_OPEN_POSITION_LOW_DPI;
		}
	}*/

	public static HashMap<String,String> htmlEnvelope( )
	{
		SFApplication application = SFApplication.getInstance();
		String fontSize;
		String lineHeight;
		if(application.getFontSize().equals( "size_small" ))
		{
			fontSize = application.getString( R.string.sf_font_size_small )+"px";
			lineHeight = application.getString( R.string.sf_line_height_small );
		}
		else if(application.getFontSize().equals( "size_large" ))
		{
			fontSize = application.getString( R.string.sf_font_size_large )+"px";
			lineHeight = application.getString( R.string.sf_line_height_large );
		}
		else
		{
			fontSize = application.getString( R.string.sf_font_size_regular )+"px";;
			lineHeight = application.getString( R.string.sf_line_height_regular );
		}
		HashMap<String,String> returnValue = new HashMap<String, String>();
		returnValue.put( "head",
		"<html>\n" +
		"	<head>\n" +
		"		<style>\n" +
		/*"			@font-face\n" +
		"			{\n" +
		"				font-family: 'Open Sans';" +
		"				font-weight: normal;\n" +
		"				font-style: normal;" +
		"			}\n" +*/
		"			body\n" +
		"			{\n" +
		"				font-size:" + fontSize +";\n" +
		"				font-family:\'Open Sans\';\n" +//font-family:serif,Helvetica,sans-serif;\n" +
		"				color:#E0E0E0;\n" +
		"				background:#272727;\n" +
		"				margin-left:18px;\n"+
		"				margin-right:18px;\n" +
		"				margin-bottom:40px;\n" +
		"				line-height:" + lineHeight + ";\n" +
		"				-webkit-user-select: none;\n"+
		"				user-select: none;\n"+
		"			}\n" +
		"			body *:not(a) { color:#E0E0E0 !important; }\n" +
		"			a,a:visited\n" +
		"			{\n" +
		"				color:#fffac2 !important;\n" +
		"				<!-- text-decoration:none !important; -->\n" +
		"			}\n" +
		"			img, iframe\n" +
		"			{\n" +
		"				max-width: 100% !important;\n" +
		"				height: auto;\n" +
		"			}\n" +
		"			.sflb_section " +
		"			{\n" +
		"				background:none !important;\n" +
		"				width: 100% !important;\n" +
		"			}\n" +
		"		</style>\n" +
		"	</head>\n" +
		"<body height='100%' width='100%'>\n" );

		returnValue.put( "tail",
		"	</body>\n" +
		"</html>" );

		return returnValue;
	}

	public static String htmlFullScreenVideoEnvelope( String url )
	{
		SFApplication application = SFApplication.getInstance();
		//HashMap<String,String> returnValue = new HashMap<String, String>();

		String returnValue =
				"<html>\n" +
						"	<head>\n" +
						"		<style>\n" +
						"			body\n" +
						"			{\n" +
						"				background:#272727;\n" +
						"				margin:0px;\n" +
						"				padding:0px;\n" +
						"				-webkit-user-select: none;\n"+
						"				user-select: none;\n"+
						"			}\n" +
						"			img, iframe\n" +
						"			{\n" +
						"				width: 100% !important;\n" +
						"				height: 100% !important;\n" +
						"			}\n" +
						"		</style>\n" +
						"	</head>\n" +
						"<body height='100%' width='100%'>\n" +
						url +
						"	</body>\n" +
						"</html>";

		return returnValue;
	}

	public static boolean emailIsValid( String input )
	{
		boolean returnValue = true;

		if( input.length() < 6 )
		{
			returnValue = false;
		}
		else
		{
			String[] split = input.split( "@" );
			if( split.length != 2 || split[0].length() < 1 || split[1].length() < 4 )
			{
				returnValue = false;
			}
		}


		return returnValue;
	}

	public static void logSiteEvent( String message )
	{
		if( SFConstants.TRACK_ANALYTICS )
		{
			Map<String, String> eventParams = new HashMap<String, String>();
			eventParams.put( "userTag", SFConstants.ANALYTICS_TAG );
		}
	}

	public static float dp2px( int dp )
	{
		SFApplication application = SFApplication.getInstance();
		Resources r = application.getCurrentActivity().getResources();
		return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics() );
	}

	/*
	public static float px2dp( int px )
	{
		float logicalDensity = SFUtil.displayMetrics().density;
		return (px / logicalDensity);
	}*/

	public static long currentTimestamp()
	{
		return System.currentTimeMillis()/1000;
	}

	public static String md5( String md5 )
	{
		try
		{
			java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" );
			byte[] array = md.digest( md5.getBytes() );
			StringBuffer sb = new StringBuffer();
			for( int i = 0; i < array.length; ++i )
			{
				sb.append( Integer.toHexString( ( array[ i ] & 0xFF ) | 0x100 ).substring( 1, 3 ) );
			}
			return sb.toString();
		}
		catch( java.security.NoSuchAlgorithmException e )
		{
		}
		return null;
	}


	public static byte[] createChecksum( String filename ) throws Exception
	{
		File file = new File(filename);
		if(file.exists())
		{
			InputStream fis = new FileInputStream( filename );

			byte[] buffer = new byte[1024];
			MessageDigest complete = MessageDigest.getInstance( "MD5" );
			int numRead;

			do
			{
				numRead = fis.read( buffer );
				if (numRead > 0)
				{
					complete.update( buffer, 0, numRead );
				}
			}
			while (numRead != -1);

			fis.close();
			return complete.digest();
		}
		else
		{
			return null;
		}
	}

	// see this How-to for a faster way to convert
	// a byte array to a HEX string
	public static String md5HashOfPath( String filename ) throws Exception
	{
		byte[] b = createChecksum( filename );
		String result = "";

		for (int i = 0; i < b.length; i++)
		{
			result += Integer.toString( (b[i] & 0xff) + 0x100, 16 ).substring( 1 );
		}
		return result;
	}
	public void hashAll()
	{
		Thread t = new Thread(
				new Runnable()
				{
					@Override
					public void run()
					{
						//hashOfBase();
						hashObjects();
					}
				}
		);
		t.start();
	}

	public void hashOfBase()
	{
		AiDb db = SFApplication.getInstance().getDb();
		String sql = "SELECT meta_key,meta_value " +
				"FROM section_content_meta " +
				"WHERE  section_content_id " +
				"= 1"
				;
		String[][] results = db.query( sql );
		//Log.d( "mtag","hash query results = "+ results[0][0] + ", " + results[0][1] + "\n" +results[1][0] + ", " + results[1][1]);
		HashMap<String,String> hashMap = new HashMap<String, String>(  );
		for(int i = 0; i < results.length; i++)
		{
			hashMap.put( results[i][0],results[i][1] );
		}
		String result[] = new String[3];
		result[0] += hashMap.get( "email" );
		result[0] += hashMap.get( "phone" );
		result[0] += hashMap.get( "facebook" );
		result[0] += hashMap.get( "twitter" );
		result[0] += hashMap.get( "content" );

		result[1] += hashMap.get( "address" );
		result[1] += hashMap.get( "city" );
		result[1] += hashMap.get( "state" );
		result[1] += hashMap.get( "zip" );

		result[2] += hashMap.get( "donateurl" );

		String[] hash = new String[3];
		for( int i = 0; i < hash.length; i++ )
		{
			hash[i] = md5( result[i] );
		}

		sql = "INSERT INTO sync_objects " +
				"( hash_value, object_type ) " +
				"VALUE " + hash[0] +"," + "connect "
				;
		db.query( sql );

		sql = "INSERT INTO sync_objects " +
				"( hash_value, object_type ) " +
				"VALUE " + hash[1] +"," + "location "
		;
		db.query( sql );

		sql = "INSERT INTO sync_objects " +
				"( hash_value, object_type ) " +
				"VALUE " + hash[2] +"," + "donate "
		;
		db.query( sql );

	}

	public void hashObjects()
	{
		SFAppData data = new SFAppData();
		AiDb db = SFApplication.getInstance().getDb();
		String sql = "	SELECT COUNT(*) " +
				"		AS count " +
				"		FROM section_content"
				;
		String[][] result = db.query( sql );
		int count = AiSTr.denullifyInt( result[0][0] );
		ArrayList allObjectsHashData = new ArrayList(  );
		for( int i = 0; i < count; i++)
		{
			allObjectsHashData.add( getSyncdata( i ) );
		}
		data.firstTimeAddHashes( allObjectsHashData );
	}

	public String[] getSyncdata(int id)
	{
		SFAppData data = new SFAppData();
		String[] returnValue = new String[3];

		String tag = data.getTagById( id );
		ArrayList<String> metaDataToQuery = data.getHashFieldMap( tag );
		String stringToHash = new String( "" );
		for(int i = 0; i < metaDataToQuery.size(); i++ )
		{
			stringToHash += metaDataToQuery.get( i );
		}
		Integer externalId = data.getExternalIdById( id );
		returnValue[0] = externalId.toString();
		returnValue[1] = md5( stringToHash );
		returnValue[2] = tag;

		//data.addHash( id,stringToHash,tag );
		//if( type.equals( "" ))

		return returnValue;
	}


	public static CharSequence stripHtml( String input )
	{
		return Html.fromHtml( input ).
				toString().
				replace( '\n', (char) 32 ).
				replace( (char) 160, (char) 32 ).
				replace( (char) 65532, (char) 32 ).
				trim();
	}

	public static BitmapFactory.Options commonImgOpt()
	{

		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inSampleSize = 2;
		options.inScaled = false;

		//Still 768kb each with this:
		/*options.inScaled = true;
		options.inDensity = 1;//0=default from img
		options.inTargetDensity = 0; // from DisplayMetrics
		*/
		return options;
	}

	public static String stripImg(String input)
	{
		String out = input;
		int startImg = out.indexOf("<img");
		if( startImg >-1 && startImg <300 )
		{
			//Weird, Android Studio's inspector doesn't show nbsp in string.
			out = out.substring(0, startImg).replaceAll("<div>(\\s*)&nbsp;(\\s*)</div>", "<!-- space removed -->") +
				out.substring( startImg );
		}
		// ? so it does non-greedy match, not matching <img></a></p> and making all a link for example.
		out = out.replaceAll("<img(.*?)>", "").replaceAll("</img>", "");
		return out;
	}

	// http://stackoverflow.com/questions/3382996/how-to-unzip-files-programmatically-in-android
	public static boolean unpackZip( String path, String zipname )
	{
		InputStream is;
		ZipInputStream zis;

		// append trailing slash to path if it isn't there already
		String lastPathChar = path.substring( (path.length() - 1) );
		if( !lastPathChar.equals( "/" ) )
		{
			path = path + "/";
		}

		try
		{
			String filename;
			is = new FileInputStream( path + zipname );
			zis = new ZipInputStream( new BufferedInputStream( is ) );
			ZipEntry ze;
			byte[] buffer = new byte[1024];
			int count;

			while( (ze = zis.getNextEntry()) != null )
			{
				filename = ze.getName();

				// Need to create directories if not exists, or
				// it will generate an Exception...
				if( ze.isDirectory() )
				{
					File fmd = new File( path + filename );
					fmd.mkdirs();
					continue;
				}

				FileOutputStream fout = new FileOutputStream( path + filename );

				// cteni zipu a zapis
				while( (count = zis.read( buffer )) != -1 )
				{
					fout.write( buffer, 0, count );
				}

				fout.close();
				zis.closeEntry();
			}

			zis.close();
		}
		catch( IOException e )
		{
			e.printStackTrace();
			return false;
		}

		return true;
	}

	public static Intent getFacebookIntent( String url, Context context )
	{
		try
		{
			URI uri = new URI( url );
			String path = uri.getPath();
			String id = path.substring( path.lastIndexOf( "/" ) + 1 ).trim();

			String after = id.replaceAll( "[^0-9]", "" );

			// The URL ends with an ID
			if( id.equals( after ) )
			{
				try
				{
					// if no exception, the user has the Facebook app installed
					context.getPackageManager().getPackageInfo( "com.facebook.katana", 0 );
					return new Intent( Intent.ACTION_VIEW, Uri.parse( "fb://page/" + id ) );
				}
				catch (Exception e)
				{
					// or else, no Facebook app, so we should open in a browser
					return new Intent( Intent.ACTION_VIEW, Uri.parse( url ) );
				}
			}

		}
		catch( Exception e )
		{
			e.printStackTrace();
		}

		// If we make it here, the Facebook URL doesn't end in an ID or the URI parse failed
		return new Intent( Intent.ACTION_VIEW, Uri.parse( url ) );
	}

}
