content: /*
   * Androzic - android navigation client that uses OziExplorer maps (ozf2, ozfx3).
   * Copyright (C) 2010-2012 Andrey Novikov <http://andreynovikov.info/>
   * 
   * This file is part of Androzic application.
   * 
   * Androzic is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   * 
   * Androzic is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   * GNU General Public License for more details.
   * 
   * You should have received a copy of the GNU General Public License
   * along with Androzic. If not, see <http://www.gnu.org/licenses/>.
   */
  
  package com.androzic;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.List;
  import java.util.Locale;
  
  import android.annotation.SuppressLint;
  import android.app.Activity;
  import android.app.Dialog;
  import android.content.DialogInterface;
  import android.content.DialogInterface.OnKeyListener;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.content.SharedPreferences.Editor;
  import android.content.res.Resources;
  import android.database.Cursor;
  import android.database.sqlite.SQLiteDatabase;
  import android.os.Bundle;
  import android.os.Environment;
  import android.os.Handler;
  import android.os.Message;
  import android.preference.PreferenceManager;
  import android.support.v7.app.AlertDialog;
  import android.text.Html;
  import android.text.SpannableString;
  import android.text.method.LinkMovementMethod;
  import android.text.util.Linkify;
  import android.util.DisplayMetrics;
  import android.util.Log;
  import android.view.KeyEvent;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.view.Window;
  import android.widget.Button;
  import android.widget.ProgressBar;
  import android.widget.TextView;
  
  import com.androzic.data.Route;
  import com.androzic.data.Track;
  import com.androzic.overlay.CurrentTrackOverlay;
  import com.androzic.util.AutoloadedRouteFilenameFilter;
  import com.androzic.util.FileList;
  import com.androzic.util.GpxFiles;
  import com.androzic.util.KmlFiles;
  import com.androzic.util.OziExplorerFiles;
  
  public class Splash extends Activity implements OnClickListener
  {
  	private static final int MSG_FINISH = 1;
  	private static final int MSG_ERROR = 2;
  	private static final int MSG_STATUS = 3;
  	private static final int MSG_PROGRESS = 4;
  	private static final int MSG_ASK = 5;
  	private static final int MSG_SAY = 6;
  
  	private static final int RES_YES = 1;
  	private static final int RES_NO = 2;
  
  	private static final int PROGRESS_STEP = 10000;
  
  	@SuppressWarnings("unused")
  	private int result;
  	private boolean wait;
  	protected String savedMessage;
  	private ProgressBar progress;
  	private TextView message;
  	private Button gotit;
  	private Button yes;
  	private Button no;
  	private Button quit;
  	protected Androzic application;
  
  	@SuppressLint("NewApi")
  	@Override
  	public void onCreate(Bundle savedInstanceState)
  	{
  		super.onCreate(savedInstanceState);
  
  		requestWindowFeature(Window.FEATURE_NO_TITLE);
  
  		application = (Androzic) getApplication();
  		application.onCreateEx();
  
  		PreferenceManager.setDefaultValues(this, R.xml.pref_behavior, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_folder, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_location, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_display, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_unit, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_tracking, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_waypoint, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_route, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_navigation, true);
  		PreferenceManager.setDefaultValues(this, R.xml.pref_general, true);
  
  		setContentView(R.layout.act_splash);
  
  		if (application.isPaid)
  		{
  			findViewById(R.id.paid).setVisibility(View.VISIBLE);
  		}
  
  		progress = (ProgressBar) findViewById(R.id.progress);
  		message = (TextView) findViewById(R.id.message);
  
  		message.setText(getString(R.string.msg_wait));
  		progress.setMax(PROGRESS_STEP * 4);
  
  		yes = (Button) findViewById(R.id.yes);
  		yes.setOnClickListener(this);
  		no = (Button) findViewById(R.id.no);
  		no.setOnClickListener(this);
  		gotit = (Button) findViewById(R.id.gotit);
  		gotit.setOnClickListener(this);
  		quit = (Button) findViewById(R.id.quit);
  		quit.setOnClickListener(this);
  
  		wait = true;
  
  		showEula();
  
  		if (!application.mapsInited)
  		{
  			new InitializationThread(progressHandler).start();
  		}
  		else
  		{
  			progressHandler.sendEmptyMessage(MSG_FINISH);
  		}
  	}
  
  	private void showEula()
  	{
  		final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
  		boolean hasBeenShown = prefs.getBoolean(getString(R.string.app_eulaaccepted), false);
  		if (hasBeenShown == false)
  		{
  			final SpannableString message = new SpannableString(Html.fromHtml(getString(R.string.app_eula).replace("/n", "<br/>")));
  			Linkify.addLinks(message, Linkify.WEB_URLS);
  
  			AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle(getString(R.string.app_name)).setIcon(R.drawable.icon).setMessage(message)
  					.setPositiveButton(android.R.string.ok, new Dialog.OnClickListener() {
  						@Override
  						public void onClick(DialogInterface dialogInterface, int i)
  						{
  							prefs.edit().putBoolean(getString(R.string.app_eulaaccepted), true).commit();
  							wait = false;
  							dialogInterface.dismiss();
  						}
  					}).setOnKeyListener(new OnKeyListener() {
  						@Override
  						public boolean onKey(DialogInterface dialoginterface, int keyCode, KeyEvent event)
  						{
  							return !(keyCode == KeyEvent.KEYCODE_HOME);
  						}
  					}).setCancelable(false);
  
  			AlertDialog d = builder.create();
  
  			d.show();
  			// Make the textview clickable. Must be called after show()
  			((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
  		}
  		else
  		{
  			wait = false;
  		}
  	}
  
  	final Handler progressHandler = new Handler() {
  		public void handleMessage(Message msg)
  		{
  			switch (msg.what)
  			{
  				case MSG_STATUS:
  					message.setText(msg.getData().getString("message"));
  					break;
  				case MSG_PROGRESS:
  					int total = msg.getData().getInt("total");
  					progress.setProgress(total);
  					break;
  				case MSG_ASK:
  					progress.setVisibility(View.GONE);
  					savedMessage = message.getText().toString();
  					message.setText(msg.getData().getString("message"));
  					result = 0;
  					yes.setVisibility(View.VISIBLE);
  					no.setVisibility(View.VISIBLE);
  					break;
  				case MSG_SAY:
  					progress.setVisibility(View.GONE);
  					savedMessage = message.getText().toString();
  					message.setText(msg.getData().getString("message"));
  					result = 0;
  					gotit.setVisibility(View.VISIBLE);
  					break;
  				case MSG_FINISH:
  					startActivity(new Intent(Splash.this, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK).putExtras(getIntent()));
  					finish();
  					break;
  				case MSG_ERROR:
  					progress.setVisibility(View.INVISIBLE);
  					message.setText(msg.getData().getString("message"));
  					quit.setVisibility(View.VISIBLE);
  					break;
  			}
  		}
  	};
  
  	private class InitializationThread extends Thread
  	{
  		Handler mHandler;
  		int total;
  
  		InitializationThread(Handler h)
  		{
  			mHandler = h;
  		}
  
  		public void run()
  		{
  			while (wait)
  			{
  				try
  				{
  					sleep(100);
  				}
  				catch (InterruptedException e)
  				{
  					e.printStackTrace();
  				}
  			}
  
  			total = 0;
  
  			Message msg = mHandler.obtainMessage(MSG_STATUS);
  			Bundle b = new Bundle();
  			b.putString("message", getString(R.string.msg_initializingdata));
  			msg.setData(b);
  			mHandler.sendMessage(msg);
  
  			Resources resources = getResources();
  			SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(Splash.this);
  
  			// start location service
  			application.enableLocating(settings.getBoolean(getString(R.string.lc_locate), true));
  
  			// set root folder and check if it has to be created
  			String rootPath = settings.getString(getString(R.string.pref_folder_root), Environment.getExternalStorageDirectory() + File.separator + resources.getString(R.string.def_folder_prefix));
  			File root = new File(rootPath);
  			if (!root.exists())
  			{
  				try
  				{
  					root.mkdirs();
  					File nomedia = new File(root, ".nomedia");
  					nomedia.createNewFile();
  				}
  				catch (IOException e)
  				{
  					msg = mHandler.obtainMessage(MSG_ERROR);
  					b = new Bundle();
  					b.putString("message", getString(R.string.err_nosdcard));
  					msg.setData(b);
  					mHandler.sendMessage(msg);
  					return;
  				}
  			}
  
  			// check maps folder existence
  			File mapdir = new File(settings.getString(getString(R.string.pref_folder_map), Environment.getExternalStorageDirectory() + File.separator + resources.getString(R.string.def_folder_map)));
  			String oldmap = settings.getString(getString(R.string.pref_folder_map_old), null);
  			if (oldmap != null)
  			{
  				File oldmapdir = new File(root, oldmap);
  				if (!oldmapdir.equals(mapdir))
  				{
  					mapdir = oldmapdir;
  					Editor editor = settings.edit();
  					editor.putString(getString(R.string.pref_folder_map), mapdir.getAbsolutePath());
  					editor.putString(getString(R.string.pref_folder_map_old), null);
  					editor.commit();
  				}
  			}
  			if (!mapdir.exists())
  			{
  				mapdir.mkdirs();
  			}
  
  			// check data folder existence
  			File datadir = new File(settings.getString(getString(R.string.pref_folder_data), Environment.getExternalStorageDirectory() + File.separator + resources.getString(R.string.def_folder_data)));
  			if (!datadir.exists())
  			{
  				// check if there was an old data structure
  				String wptdir = settings.getString(getString(R.string.pref_folder_waypoint), null);
  				System.err.println("wpt: " + wptdir);
  				if (wptdir != null)
  				{
  					wait = true;
  					msg = mHandler.obtainMessage(MSG_SAY);
  					b = new Bundle();
  					b.putString("message", getString(R.string.msg_newdatafolder, datadir.getAbsolutePath()));
  					msg.setData(b);
  					mHandler.sendMessage(msg);
  
  					while (wait)
  					{
  						try
  						{
  							sleep(100);
  						}
  						catch (InterruptedException e)
  						{
  							e.printStackTrace();
  						}
  					}
  				}
  				datadir.mkdirs();
  			}
  
  			// old icons are used by plugins so far
  			File iconsdir = new File(settings.getString(getString(R.string.pref_folder_icon), Environment.getExternalStorageDirectory() + File.separator + resources.getString(R.string.def_folder_icon)));
  			// check marker icons folder existence
  			File markericonsdir = new File(settings.getString(getString(R.string.pref_folder_markericon), Environment.getExternalStorageDirectory() + File.separator + resources.getString(R.string.def_folder_markericon)));
  			if (!markericonsdir.exists())
  			{
  				try
  				{
  					markericonsdir.mkdirs();
  					int dpi = resources.getDisplayMetrics().densityDpi;
  					String dpiEx = "xxxhdpi";
  					if (dpi <= DisplayMetrics.DENSITY_XXHIGH)
  						dpiEx = "xxhdpi";
  					if (dpi <= DisplayMetrics.DENSITY_XHIGH)
  						dpiEx = "xhdpi";
  					if (dpi <= DisplayMetrics.DENSITY_HIGH)
  						dpiEx = "hdpi";
  					if (dpi <= DisplayMetrics.DENSITY_MEDIUM)
  						dpiEx = "mdpi";
  					File nomedia = new File(markericonsdir, ".nomedia");
  					nomedia.createNewFile();
  					application.copyAssets("icons-" + dpiEx, markericonsdir);
  				}
  				catch (IOException e)
  				{
  					e.printStackTrace();
  				}
  			}
  
  			// initialize paths
  			application.setRootPath(root.getAbsolutePath());
  			application.setMapPath(mapdir.getAbsolutePath());
  			application.setDataPath(Androzic.PATH_DATA, datadir.getAbsolutePath());
  			application.setDataPath(Androzic.PATH_ICONS, iconsdir.getAbsolutePath());
  			application.setDataPath(Androzic.PATH_MARKERICONS, markericonsdir.getAbsolutePath());
  
  			// initialize data
  			application.installData();
  
  			// start tracking service
  			application.enableTracking(settings.getBoolean(getString(R.string.lc_track), true));
  
  			// read waypoints
  			application.initializeWaypoints();
  
  			// read track tail
  			if (settings.getBoolean(getString(R.string.pref_showcurrenttrack), true))
  			{
  				application.overlayManager.currentTrackOverlay = new CurrentTrackOverlay();
  				if (settings.getBoolean(getString(R.string.pref_tracking_currentload), resources.getBoolean(R.bool.def_tracking_currentload)))
  				{
  					int length = Integer.parseInt(settings.getString(getString(R.string.pref_tracking_currentlength), getString(R.string.def_tracking_currentlength)));
  					// TODO Move this to proper class
  					File path = new File(application.dataPath, "myTrack.db");
  					try
  					{
  						SQLiteDatabase trackDB = SQLiteDatabase.openDatabase(path.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
  						Cursor cursor = trackDB.rawQuery("SELECT * FROM track ORDER BY _id DESC LIMIT " + length, null);
  						if (cursor.getCount() > 0)
  						{
  							Track track = new Track();
  							for (boolean hasItem = cursor.moveToLast(); hasItem; hasItem = cursor.moveToPrevious())
  							{
  								double latitude = cursor.getDouble(cursor.getColumnIndex("latitude"));
  								double longitude = cursor.getDouble(cursor.getColumnIndex("longitude"));
  								double altitude = cursor.getDouble(cursor.getColumnIndex("elevation"));
  								double speed = cursor.getDouble(cursor.getColumnIndex("speed"));
  								double bearing = cursor.getDouble(cursor.getColumnIndex("track"));
  								double accuracy = cursor.getDouble(cursor.getColumnIndex("accuracy"));
  								int code = cursor.getInt(cursor.getColumnIndex("code"));
  								long time = cursor.getLong(cursor.getColumnIndex("datetime"));
  								boolean continous = cursor.isFirst() || cursor.isLast() ? false : code == 0;
  								track.addPoint(continous, latitude, longitude, altitude, speed, bearing, accuracy, time);
  							}
  							track.show = true;
  							application.overlayManager.currentTrackOverlay.setTrack(track);
  						}
  						cursor.close();
  						trackDB.close();
  					}
  					catch (Exception e)
  					{
  						Log.e("Splash", "Read track tail", e);
  					}
  				}
  			}
  			// load routes
  			if (settings.getBoolean(getString(R.string.pref_route_preload), resources.getBoolean(R.bool.def_route_preload)))
  			{
  				boolean hide = settings.getBoolean(getString(R.string.pref_route_preload_hidden), resources.getBoolean(R.bool.def_route_preload_hidden));
  				List<File> files = FileList.getFileListing(new File(application.dataPath), new AutoloadedRouteFilenameFilter());
  				for (File file : files)
  				{
  					List<Route> routes = null;
  					try
  					{
  						String lc = file.getName().toLowerCase(Locale.getDefault());
  						if (lc.endsWith(".rt2") || lc.endsWith(".rte"))
  						{
  							routes = OziExplorerFiles.loadRoutesFromFile(file, application.charset);
  						}
  						else if (lc.endsWith(".kml"))
  						{
  							routes = KmlFiles.loadRoutesFromFile(file);
  						}
  						else if (lc.endsWith(".gpx"))
  						{
  							routes = GpxFiles.loadRoutesFromFile(file);
  						}
  						for (Route route : routes)
  						{
  							route.show = !hide;
  							application.addRoute(route);
  						}
  					}
  					catch (Exception e)
  					{
  						e.printStackTrace();
  					}
  				}
  			}
  			
  			application.overlayManager.init();
  
  			total += PROGRESS_STEP;
  			msg = mHandler.obtainMessage(MSG_PROGRESS);
  			b = new Bundle();
  			b.putInt("total", total);
  			msg.setData(b);
  			mHandler.sendMessage(msg);
  
  			// put world map if no any found
  			String[] mapfiles = mapdir.list();
  			if (Variants.ALWAYS_WRITE_MAP_ASSETS || mapfiles != null && mapfiles.length == 0)
  				application.copyAssets("maps", mapdir);
  
  			msg = mHandler.obtainMessage(MSG_STATUS);
  			b = new Bundle();
  			b.putString("message", getString(R.string.msg_initializingmaps));
  			msg.setData(b);
  			mHandler.sendMessage(msg);
  
  			// initialize maps
  			application.initializeMaps();
  			application.moveTileCache();
  
  			total += PROGRESS_STEP;
  			msg = mHandler.obtainMessage(MSG_PROGRESS);
  			b = new Bundle();
  			b.putInt("total", total);
  			msg.setData(b);
  			mHandler.sendMessage(msg);
  
  			msg = mHandler.obtainMessage(MSG_STATUS);
  			b = new Bundle();
  			b.putString("message", getString(R.string.msg_initializingplugins));
  			msg.setData(b);
  			mHandler.sendMessage(msg);
  
  			// initialize plugins
  			application.initializePlugins();
  
  			total += PROGRESS_STEP;
  			msg = mHandler.obtainMessage(MSG_PROGRESS);
  			b = new Bundle();
  			b.putInt("total", total);
  			msg.setData(b);
  			mHandler.sendMessage(msg);
  
  			msg = mHandler.obtainMessage(MSG_STATUS);
  			b = new Bundle();
  			b.putString("message", getString(R.string.msg_initializingview));
  			msg.setData(b);
  			mHandler.sendMessage(msg);
  
  			// initialize current map
  			application.initializeMapCenter();
  
  			// initialize navigation
  			application.initializeNavigation();
  			
  			total += PROGRESS_STEP;
  			msg = mHandler.obtainMessage(MSG_PROGRESS);
  			b = new Bundle();
  			b.putInt("total", total);
  			msg.setData(b);
  			mHandler.sendMessage(msg);
  
  			mHandler.sendEmptyMessage(MSG_FINISH);
  		}
  	}
  
  	@Override
  	public void onClick(View v)
  	{
  		switch (v.getId())
  		{
  			case R.id.yes:
  				result = RES_YES;
  				break;
  			case R.id.no:
  				result = RES_NO;
  				break;
  			case R.id.quit:
  				finish();
  				break;
  		}
  		gotit.setVisibility(View.GONE);
  		yes.setVisibility(View.GONE);
  		no.setVisibility(View.GONE);
  		progress.setVisibility(View.VISIBLE);
  		message.setText(savedMessage);
  		wait = false;
  	}
  }
  