/*
 * Copyright (c) 2015. Ncomz. All Rights Reserved
 */

package com.google.zxing.client.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.Result;
import com.google.zxing.ResultMetadataType;
import com.google.zxing.client.android.camera.CameraManager;
import com.google.zxing.client.android.result.ResultHandler;
import com.google.zxing.client.android.result.ResultHandlerFactory;
import com.ntels.kneet.v3.R;
import com.ntels.kneet.v3.common.AppConfig;
import com.ntels.kneet.v3.common.Constants;
import com.ntels.kneet.v3.common.util.Dlog;
import com.ntels.kneet.v3.common.util.Util;
import com.ntels.kneet.v3.view.dialog.CustomDialog;
import com.ntels.kneet.v3.view.things.Things_Homehub_Input;
import com.tsengvn.typekit.TypekitContextWrapper;

import java.io.IOException;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;

public final class Reader_Qr extends Activity implements SurfaceHolder.Callback,
                                                         View.OnClickListener,
                                                         CustomDialog.OnMsgAlterToResult {

    private static final String TAG = Reader_Qr.class.getSimpleName();

    private Activity act;
    Intent intent;
    private AppConfig appConfig;
    private              Util         util                              = new Util();
    private              CustomDialog customDialog                      = new CustomDialog();
    private static final long         DEFAULT_INTENT_RESULT_DURATION_MS = 1500L;
    private static final long         BULK_MODE_SCAN_DELAY_MS           = 1000L;

    private static final String[] ZXING_URLS = {"http://zxing.appspot.com/scan", "zxing://scan/"};

    public static final int HISTORY_REQUEST_CODE = 0x0000bacc;

    private static final Collection<ResultMetadataType> DISPLAYABLE_METADATA_TYPES = EnumSet.of(ResultMetadataType.ISSUE_NUMBER, ResultMetadataType.SUGGESTED_PRICE,
                                                                                                ResultMetadataType.ERROR_CORRECTION_LEVEL, ResultMetadataType.POSSIBLE_COUNTRY);

    private CameraManager             cameraManager;
    private CaptureActivityHandler    handler;
    private Result                    savedResultToShow;
    private ViewfinderView            viewfinderView;
    //	private TextView                  statusView;
    //	private View                      resultView;
    private Result                    lastResult;
    private boolean                   hasSurface;
    private boolean                   copyToClipboard;
    private IntentSource              source;
    private String                    sourceUrl;
    private ScanFromWebPageManager    scanFromWebPageManager;
    private Collection<BarcodeFormat> decodeFormats;
    private Map<DecodeHintType, ?>    decodeHints;
    private String                    characterSet;
    private InactivityTimer           inactivityTimer;
    private BeepManager               beepManager;
    private String sActivation_Code = "";
    private String sPass            = "";
    //  private AmbientLightManager ambientLightManager;

    ViewfinderView getViewfinderView() {

        return viewfinderView;
    }

    public Handler getHandler() {

        return handler;
    }

    CameraManager getCameraManager() {

        return cameraManager;
    }

    @Override public void onStop() {

        super.onStop();
        Dlog.v("onStop()");
        GoogleAnalytics.getInstance(act).reportActivityStop(act);
    }

    @Override public void onStart() {

        super.onStart();
        Dlog.v("onStart()");
        GoogleAnalytics.getInstance(act).reportActivityStart(act);
    }

    @Override protected void attachBaseContext(Context newBase) {

        super.attachBaseContext(TypekitContextWrapper.wrap(newBase));
    }
    @Override public void onCreate(Bundle icicle) {

        super.onCreate(icicle);
        act = this;

        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.reader_qr);

        hasSurface = false;
        inactivityTimer = new InactivityTimer(this);
        beepManager = new BeepManager(this);
        //    ambientLightManager = new AmbientLightManager(this);

        //    PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
        util.getView(act, R.id.llBtn1).setOnClickListener(this);
        util.getView(act, R.id.llBtn2).setOnClickListener(this);
        customDialog.setOnMsgAlterToResultEvent(this);

        //        Tracker t = appConfig.getTracker(AppConfig.TrackerName.APP_TRACKER);
        //        t.setScreenName(act.getClass().getSimpleName());
        //        t.send(new HitBuilders.AppViewBuilder().build());
        util.callActGoogleAnalytics(act);
    }

    @Override public void onClick(View v) {

        Intent intent;
        switch (v.getId()) {
            case R.id.llBtn1:
                intent = new Intent(act, Things_Homehub_Input.class);
                util.callActivityForResultNoAnim(act, intent, Constants.ACT_THINGS_HOMEHUB_INPUT);
                break;
            case R.id.llBtn2:
                onBackPressed();
                break;
            default:
                break;
        }
    }

    @Override protected void onResume() {

        super.onResume();

        // CameraManager must be initialized here, not in onCreate(). This is necessary because we don't
        // want to open the camera driver and measure the screen size if we're going to show the help on
        // first launch. That led to bugs where the scanning rectangle was the wrong size and partially
        // off screen.
        cameraManager = new CameraManager(getApplication());

        viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
        viewfinderView.setCameraManager(cameraManager);

        //		resultView = findViewById(R.id.result_view);
        //		statusView = (TextView) findViewById(R.id.status_view);

        handler = null;
        lastResult = null;

        //    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

        //    if (prefs.getBoolean(PreferencesActivity.KEY_DISABLE_AUTO_ORIENTATION, true)) {
        //      setRequestedOrientation(getCurrentOrientation());
        //    } else {
        //      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
        //    }

        resetStatusView();

        beepManager.updatePrefs();
        //    ambientLightManager.start(cameraManager);

        inactivityTimer.onResume();

        Intent intent = getIntent();

        //    copyToClipboard = prefs.getBoolean(PreferencesActivity.KEY_COPY_TO_CLIPBOARD, true)
        //        && (intent == null || intent.getBooleanExtra(Intents.Scan.SAVE_HISTORY, true));

        source = IntentSource.NONE;
        sourceUrl = null;
        scanFromWebPageManager = null;
        decodeFormats = null;
        characterSet = null;

        if ( intent != null ) {

            String action = intent.getAction();
            String dataString = intent.getDataString();

            if ( Intents.Scan.ACTION.equals(action) ) {

                // Scan the formats the intent requested, and return the result to the calling activity.
                source = IntentSource.NATIVE_APP_INTENT;
                decodeFormats = DecodeFormatManager.parseDecodeFormats(intent);
                decodeHints = DecodeHintManager.parseDecodeHints(intent);

                if ( intent.hasExtra(Intents.Scan.WIDTH) && intent.hasExtra(Intents.Scan.HEIGHT) ) {
                    int width = intent.getIntExtra(Intents.Scan.WIDTH, 0);
                    int height = intent.getIntExtra(Intents.Scan.HEIGHT, 0);
                    if ( width > 0 && height > 0 ) {
                        cameraManager.setManualFramingRect(width, height);
                    }
                }

                if ( intent.hasExtra(Intents.Scan.CAMERA_ID) ) {
                    int cameraId = intent.getIntExtra(Intents.Scan.CAMERA_ID, -1);
                    if ( cameraId >= 0 ) {
                        cameraManager.setManualCameraId(cameraId);
                    }
                }

                //				String customPromptMessage = intent.getStringExtra(Intents.Scan.PROMPT_MESSAGE);
                //				if (customPromptMessage != null) {
                //					statusView.setText(customPromptMessage);
                //				}

            } else if ( dataString != null && dataString.contains("http://www.google") && dataString.contains("/m/products/scan") ) {

                // Scan only products and send the result to mobile Product Search.
                source = IntentSource.PRODUCT_SEARCH_LINK;
                sourceUrl = dataString;
                decodeFormats = DecodeFormatManager.PRODUCT_FORMATS;

                //			} else if (isZXingURL(dataString)) {
                //
                //				// Scan formats requested in query string (all formats if none specified).
                //				// If a return URL is specified, send the results there. Otherwise, handle it ourselves.
                //				source = IntentSource.ZXING_LINK;
                //				sourceUrl = dataString;
                //				Uri inputUri = Uri.parse(dataString);
                //				scanFromWebPageManager = new ScanFromWebPageManager(inputUri);
                //				decodeFormats = DecodeFormatManager.parseDecodeFormats(inputUri);
                //				// Allow a sub-set of the hints to be specified by the caller.
                //				decodeHints = DecodeHintManager.parseDecodeHints(inputUri);

            }

            characterSet = intent.getStringExtra(Intents.Scan.CHARACTER_SET);
        }

        SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
        SurfaceHolder surfaceHolder = surfaceView.getHolder();
        if ( hasSurface ) {
            // The activity was paused but not stopped, so the surface still exists. Therefore
            // surfaceCreated() won't be called, so init the camera here.
            initCamera(surfaceHolder);
        } else {
            // Install the callback and wait for surfaceCreated() to init the camera.
            surfaceHolder.addCallback(this);
        }
    }

    //	private int getCurrentOrientation() {
    //		int rotation = getWindowManager().getDefaultDisplay().getRotation();
    //		switch (rotation) {
    //			case Surface.ROTATION_0:
    //			case Surface.ROTATION_90:
    //				return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    //			default:
    //				return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
    //		}
    //	}

    //	private static boolean isZXingURL(String dataString) {
    //		if (dataString == null) {
    //			return false;
    //		}
    //		for (String url : ZXING_URLS) {
    //			if (dataString.startsWith(url)) {
    //				return true;
    //			}
    //		}
    //		return false;
    //	}

    @Override protected void onPause() {

        if ( handler != null ) {
            handler.quitSynchronously();
            handler = null;
        }
        inactivityTimer.onPause();
        //    ambientLightManager.stop();
        beepManager.close();
        cameraManager.closeDriver();
        //historyManager = null; // Keep for onActivityResult
        if ( !hasSurface ) {
            SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
            SurfaceHolder surfaceHolder = surfaceView.getHolder();
            surfaceHolder.removeCallback(this);
        }
        super.onPause();
    }

    @Override protected void onDestroy() {

        inactivityTimer.shutdown();
        super.onDestroy();
    }

    @Override public boolean onKeyDown(int keyCode, KeyEvent event) {

        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
                if ( source == IntentSource.NATIVE_APP_INTENT ) {
                    setResult(RESULT_CANCELED);
                    finish();
                    return true;
                }
                if ( (source == IntentSource.NONE || source == IntentSource.ZXING_LINK) && lastResult != null ) {
                    restartPreviewAfterDelay(0L);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_FOCUS:
            case KeyEvent.KEYCODE_CAMERA:
                // Handle these events so they don't launch the Camera app
                return true;
            // Use volume up/down to turn on light
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                cameraManager.setTorch(false);
                return true;
            case KeyEvent.KEYCODE_VOLUME_UP:
                cameraManager.setTorch(true);
                return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);
        if ( data == null ) {
            return;
        }
        if ( resultCode == RESULT_OK ) {
            if ( requestCode == Constants.ACT_THINGS_HOMEHUB_INPUT ) {
                sActivation_Code = data.getStringExtra(Constants.EXTRA_ACTIVATION_CODE);
                sPass = data.getStringExtra(Constants.EXTRA_PASSWORD);
                intent = new Intent();
                intent.putExtra(Constants.EXTRA_ACTIVATION_CODE, sActivation_Code);
                intent.putExtra(Constants.EXTRA_PASSWORD, sPass);
                act.setResult(RESULT_OK, intent);
                finish();
            }
        }
    }

    @Override public void onBackPressed() {

        intent = new Intent();
        //        intent.putExtra(Constants.EXTRA_RELOAD_FLAG, true);
        act.setResult(RESULT_CANCELED, intent);
        finish();
        return;
    }

    @Override public void resultCustomDialogResponse(int iMsgID, int iBtnResult) {

        switch (iMsgID) {
            case Constants.MSG861:
                if ( iBtnResult == 1 ) {
                    restartPreviewAfterDelay(0L);
                }
                break;
            default:
                break;
        }
    }
    //	private void decodeOrStoreSavedBitmap(Bitmap bitmap, Result result) {
    //		// Bitmap isn't used yet -- will be used soon
    //		if (handler == null) {
    //			savedResultToShow = result;
    //		} else {
    //			if (result != null) {
    //				savedResultToShow = result;
    //			}
    //			if (savedResultToShow != null) {
    //				Message message = Message.obtain(handler, R.id.decode_succeeded, savedResultToShow);
    //				handler.sendMessage(message);
    //			}
    //			savedResultToShow = null;
    //		}
    //	}

    @Override public void surfaceCreated(SurfaceHolder holder) {

        if ( holder == null ) {
            Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
        }
        if ( !hasSurface ) {
            hasSurface = true;
            initCamera(holder);
        }
    }

    @Override public void surfaceDestroyed(SurfaceHolder holder) {

        hasSurface = false;
    }

    @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    /**
     * A valid barcode has been found, so give an indication of success and show the results.
     *
     * @param rawResult   The contents of the barcode.
     * @param scaleFactor amount by which thumbnail was scaled
     * @param barcode     A greyscale bitmap of the camera data which was decoded.
     */
    public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {

        inactivityTimer.onActivity();
        lastResult = rawResult;
        ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);

        boolean fromLiveScan = barcode != null;
        if ( fromLiveScan ) {
            //      historyManager.addHistoryItem(rawResult, resultHandler);
            // Then not from history, so beep/vibrate and we have an image to draw on
            beepManager.playBeepSoundAndVibrate();
            //			drawResultPoints(barcode, scaleFactor, rawResult);

            Dlog.v("rawResult.toString() = " + rawResult.toString());
            if ( !rawResult.toString().contains("|*_AC_*|") ) {
                //                util.setShowToast(act, util.getString(act, R.string.MSG861) + util.getString(act, R.string.MSG901), Toast.LENGTH_SHORT);
                util.setShowToast(act, util.getString(act, R.string.MSG861) + util.getString(act, R.string.MSG901), Toast.LENGTH_SHORT);
                restartPreviewAfterDelay(0L);
                return;
            }

            String[] strArray = rawResult.toString().split("\\|\\*\\_AC\\_\\*\\|", 100);

            sActivation_Code = util.null2string(strArray[0]);
            sPass = util.null2string(strArray[1]).replaceAll("\\r\\n", "");

            if ( sActivation_Code.equals("") || sPass.equals("") ) {
                //                util.setShowToast(act, util.getString(act, R.string.MSG861) + util.getString(act, R.string.MSG901), Toast.LENGTH_SHORT);
                util.setShowToast(act, util.getString(act, R.string.MSG861) + util.getString(act, R.string.MSG901), Toast.LENGTH_SHORT);
                restartPreviewAfterDelay(0L);
                return;
            }

            intent = new Intent();
            intent.putExtra(Constants.EXTRA_ACTIVATION_CODE, sActivation_Code);
            intent.putExtra(Constants.EXTRA_PASSWORD, sPass);
            act.setResult(RESULT_OK, intent);
            finish();
        }
    }

    private void initCamera(SurfaceHolder surfaceHolder) {

        if ( surfaceHolder == null ) {
            throw new IllegalStateException("No SurfaceHolder provided");
        }
        if ( cameraManager.isOpen() ) {
            Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?");
            return;
        }
        try {
            cameraManager.openDriver(surfaceHolder);
            // Creating the handler starts the preview, which can also throw a RuntimeException.
            if ( handler == null ) {
                handler = new CaptureActivityHandler(this, decodeFormats, decodeHints, characterSet, cameraManager);
            }
            //			decodeOrStoreSavedBitmap(null, null);
        } catch (IOException ioe) {
            Log.w(TAG, ioe);
            displayFrameworkBugMessageAndExit();
        } catch (RuntimeException e) {
            // Barcode Scanner has seen crashes in the wild of this variety:
            // java.?lang.?RuntimeException: Fail to connect to camera service
            Log.w(TAG, "Unexpected error initializing camera", e);
            displayFrameworkBugMessageAndExit();
        }
    }

    private void displayFrameworkBugMessageAndExit() {

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(getString(R.string.app_name));
        builder.setMessage(getString(R.string.msg_camera_framework_bug));
        builder.setPositiveButton(R.string.button_ok, new FinishListener(this));
        builder.setOnCancelListener(new FinishListener(this));
        builder.show();
    }

    public void restartPreviewAfterDelay(long delayMS) {

        if ( handler != null ) {
            handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);
        }
        resetStatusView();
    }

    private void resetStatusView() {
        //		resultView.setVisibility(View.GONE);
        //		statusView.setText(R.string.msg_default_status);
        //		statusView.setVisibility(View.VISIBLE);
        viewfinderView.setVisibility(View.VISIBLE);
        lastResult = null;
    }

    public void drawViewfinder() {

        viewfinderView.drawViewfinder();
    }
}
