package jp.agentec.abook.abv.ui.common.util;

import jp.agentec.abook.abv.bl.acms.type.LoginMode;
import jp.agentec.abook.abv.bl.common.ABVEnvironment;
import jp.agentec.abook.abv.bl.common.Constant;
import jp.agentec.abook.abv.bl.common.Constant.AspectType;
import jp.agentec.abook.abv.bl.common.db.SQLiteDatabase;
import jp.agentec.abook.abv.bl.common.db.SQLiteOpenHelper;
import jp.agentec.abook.abv.bl.common.db.impl.StandardSQLiteOpenHelper;
import jp.agentec.abook.abv.bl.common.exception.ABVException;
import jp.agentec.abook.abv.bl.common.log.LogLevel;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.abook.abv.bl.data.DBConnector;
import jp.agentec.abook.abv.cl.environment.DeviceInfo;
import jp.agentec.abook.abv.cl.environment.NetworkAdapter;
import jp.agentec.abook.abv.cl.helper.PreferenceHelper;
import jp.agentec.abook.abv.cl.util.PreferenceUtil;
import jp.agentec.abook.abv.launcher.android.R;
import jp.agentec.abook.abv.ui.common.appinfo.AppDefType.UserPrefKey;
import jp.agentec.abook.abv.ui.home.helper.ActivityHandlingHelper;
import jp.agentec.adf.util.FileUtil;
import jp.agentec.adf.util.StringUtil;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Point;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.view.Display;
import android.view.WindowManager;

public class Initializer {
	private static final String TAG = "Initializer";

	private static Initializer initializer;

	private ABVEnvironment env;
	private Context context;
	private NetworkAdapter network;

	public static Initializer getInstance() {
		if (initializer == null) {
			synchronized (Initializer.class) {
				if (initializer == null) {
					initializer = new Initializer();
				}
			}
		}
		return initializer;
	}

	private Initializer() {
	}

	public void init(Context context) {
		Logger.i(TAG, "init() start");
		if (this.context == null) {
			this.context = context;
		}

		loadClass(); // クラスのロード
		initNetwork(); // ネットワーク初期化
		initEnv(); // 環境変数ABVEnvironment設定
		initDB(); // DB接続
		Logger.i(TAG, "init() end");
	}

	private void loadClass() {
		try {
			// 本来わざわざロードする必要はないはずだが、AsyncTaskをextendsしたクラスで、実際に使う段で以下のようなエラーが発生する
			// java.lang.NoClassDefFoundError: jp/agentec/abook/abv/ui/viewer/mupdf/AsyncTask
			// https://code.google.com/p/android/issues/detail?id=81083
			Class.forName("jp.agentec.abook.abv.ui.viewer.foxitPdf.AsyncTask");
		}
		catch(Throwable t) {
			// ignore
		}
	}

	private void initNetwork() {
		if (network == null) {
			network = NetworkAdapter.getInstance();
			network.setConnectivityManager((ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE));
			network.setWifiManager((WifiManager)context.getSystemService(Context.WIFI_SERVICE));
			//if (network.isWifiConnected()) hostName = InetAddress.getLocalHost().getHostName();
		}
	}

	public void initEnv() {
		env = ABVEnvironment.getInstance();
		if (!env.isInitialized()) {
			int logLevel = i(R.integer.log_level);
			boolean isDebugMode = LogLevel.level(logLevel).level() <= LogLevel.debug.level();
			env.appVersion = s(R.string.version_name);
			if (i(R.integer.login_mode) != LoginMode.SITE_PATH_ID_PASS) {
				env.acmsAddress = StringUtil.addSlashToUrlString(s(R.string.acms_address));
				env.downloadServerAddress = StringUtil.addSlashToUrlString(s(R.string.download_server_address));
				env.websocketServerHttpUrl = s(R.string.websocket_server_http_url);
				env.websocketServerWsUrl = s(R.string.websocket_server_ws_url);
			}
			env.isCheckInvalidPasswordLimit = b(R.bool.is_check_invalid_passward_limit);
			env.isContentProtected = b(R.bool.content_protected);
			env.isPdfThumbnailOutput = b(R.bool.pdf_thumbnail_output);
			env.defaultLogName = s(R.string.default_log_name);
			env.websocketDebug = b(R.bool.websocket_debug);
			env.setLogLevel(LogLevel.level(logLevel));
			env.mainFolderName = s(R.string.top);
			env.rootDirectory = context.getFilesDir().getPath();
			Logger.d(TAG, "setRootDirectory=" + env.rootDirectory);

			env.networkAdapter = network;
			env.externalStorageDirectory = android.os.Environment.getExternalStorageDirectory().getPath();

			// 既にMacAddress使用に同意している場合はMacAddressを使う
			// 認証なしの場合はUUIDを使用する
			// Wifiがオンになっていない場合アラートを表示できないので最初の設定はログイン前に行う。例外が発生しても無視。
			try {
				env.deviceId = DeviceInfo.getDeviceId(context, isDebugMode);
				env.encryptKey = DeviceInfo.getEncryptKey(context, isDebugMode);
				env.deviceIdType = DeviceInfo.getDeviceIdType(context, isDebugMode);
			} catch (ABVException e) {
				Logger.w(TAG, "getWiFiMacAddress failed. " + e.toString()); // ignore
			}

			env.screenSizeForAcmsParam = DeviceInfo.getScreenSizeForAcmsParam(context);
			env.cacheDirectory = context.getCacheDir().getPath();
			env.cacheSize = i(R.integer.cache_size);
			env.minPageLogSecond = i(R.integer.min_page_log_second);
			Logger.setLogger(jp.agentec.abook.abv.bl.common.log.UILogger.getLogger());
			String logPath = env.cacheDirectory + "/" + ABVEnvironment.AppLogPath;
			FileUtil.createParentDirectory(logPath);
			if (i(R.integer.app_log_retention) > 0) {
				Logger logger = new Logger();
				logger.setLogPathFormat(logPath);
				logger.setRetentionPeriod(i(R.integer.app_log_retention));
				Logger.setLogger2(logger);
			}
			env.aspectType = getAspectType();

			env.setInitialized(true);

			// Helperクラス初期化
			ActivityHandlingHelper.getInstance().init(context);
			PreferenceHelper.getInstance().init(context);
		}
	}

	public void initDB() {
		//	DBを開く。マイグレーションがあれば実行されるようにする。
		DBConnector conn = DBConnector.getInstance();
		if (!conn.isOpen()) {
			Logger.i(TAG, "initDB start");
			SQLiteOpenHelper sqlLiteOpenHelper = new StandardSQLiteOpenHelper(context, DBConnector.DatabaseName, DBConnector.DatabaseVersion);
			conn.setSqlLiteOpenHelper(sqlLiteOpenHelper);
			SQLiteDatabase db = conn.getDatabase();
			db.execSQL("PRAGMA foreign_keys=ON;journal_mode=WAL;synchronous=OFF；"); // foreign keyを有効,ジャーナルモードをWAL,書き込み非同期にする
			Logger.i(TAG, "initDB end");
		}
	}

	protected String s(int id) {
		return context.getResources().getString(id);
	}

	protected int i(int id) {
		return context.getResources().getInteger(id);
	}

	protected boolean b(int id) {
		return context.getResources().getBoolean(id);
	}

	@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
	private String getAspectType() {
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		Display disp = wm.getDefaultDisplay();
		Point size = new Point();

		if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
			disp.getSize(size);
		} else {
			disp.getRealSize(size);
		}

		int x = size.x;
		int y = size.y;

		float mag = (float) Math.max(x, y) / Math.min(x, y);

		String aspectType;

		// 基準より小さければ4対3、大きければ16対9とする
		if (mag < 1.55) {
			aspectType = AspectType.ASPECT_RATIO_4_3;
		} else {
			aspectType = AspectType.ASPECT_RATIO_16_9;
		}

		return aspectType;
	}
}
