package kz.istt.locust;

import static kz.istt.locust.Tools.md5;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Space;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.Frame;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

public class ScanActivity extends Activity {

    public static final int PICK_IMAGE = 1;

    final Handler mHandler = new Handler();

    public ProgressDialog mPd=null;
    public SurfaceView surfaceView;
    //public SurfaceView svDrawingFrame;
    //public TextView txtBarcodeValue;
    private Detector barcodeDetector=null;
    private CameraSource cameraSource;
    private static final int REQUEST_CAMERA_PERMISSION = 201;
    public FloatingActionButton btnOpen = null;
    public String intentData = "";
    public boolean isEmail = false;
    public String qrcode = "";

    public TextView tvName = null;
    public TextView tvCountry = null;
    public TextView tvOrganization = null;

    public void showProgress(boolean show,String title)
    {
        if(mPd==null && show) {
            mPd = new ProgressDialog(this);
            mPd.setTitle(title);

            mPd.setMessage(getResources().getString(R.string.Wait_please));
            mPd.setCanceledOnTouchOutside(false);
            mPd.setCancelable(false);
            mPd.setIndeterminate(true);
            mPd.show();
        }
        if(mPd!=null && !show) {
            mPd.hide();
            mPd=null;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scan);

        //txtBarcodeValue = findViewById(R.id.txtBarcodeValue);
        surfaceView = findViewById(R.id.surfaceView);

        tvName = (TextView) findViewById(R.id.tvName);
        tvCountry = (TextView) findViewById(R.id.tvCountry);
        tvOrganization = (TextView) findViewById(R.id.tvOrganization);

        String serial = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

		DbOpenHelper dboh = new DbOpenHelper(this);
        SQLiteDatabase rdb = null;
        Cursor cursor = null;
        try {
            rdb = dboh.getReadableDatabase();
            String sql = """
                    select
                        cr.name as country_name,
                        cp.name as company_name,
                        t.name
                    from
                        terminals t
                        left join countries cr on cr.id=t.country_id
                        left join companies cp on cp.id=t.company_id
                    where t.del=0 and t.serial=?""";
            cursor = rdb.rawQuery(sql, new String[]{serial});
            if(cursor.moveToFirst())
            {
                tvCountry.setText(cursor.getString(cursor.getColumnIndex("country_name")));
                tvOrganization.setText(cursor.getString(cursor.getColumnIndex("company_name")));
                tvName.setText(cursor.getString(cursor.getColumnIndex("name")));
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(cursor!=null){ cursor.close(); }
            if(rdb!=null){ rdb.close(); }
        }
		dboh.close();


        //surfaceView.setZOrderOnTop(false); //CODE TO SET VIDEO VIEW TO BACK

        //svDrawingFrame = findViewById(R.id.svDrawingFrame);
        //svDrawingFrame.setZOrderOnTop(true);

        /*btnAction = findViewById(R.id.btnAction);
        btnAction.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (intentData.length() > 0) {
                    if (isEmail) {
                        //startActivity(new Intent(ScanActivity.this, EmailActivity.class).putExtra("email_address", intentData));
                    }else {
                        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(intentData)));
                    }
                }
            }
        });*/

        btnOpen = (FloatingActionButton) findViewById(R.id.btnOpen);
        btnOpen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
            }
        });

        //Если QR не работает то и не отображаю кнопки
        BarcodeDetector bDetector = new BarcodeDetector.Builder(ScanActivity.this)
				.setBarcodeFormats(Barcode.QR_CODE) // set QR code as the format type
				.build();
		if(!bDetector.isOperational()) {
            btnOpen.setVisibility(View.GONE);
            surfaceView.setVisibility(View.GONE);
		}else{
            ((TextView) findViewById(R.id.tvUpdate)).setVisibility(View.GONE);
            ((Space) findViewById(R.id.sUpdate)).setVisibility(View.GONE);
        }
		bDetector.release();

    }

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

        if (requestCode == PICK_IMAGE) {
            if (data == null) {
                return;
            }
            InputStream inputStream = null;
            try {
                inputStream = getContentResolver().openInputStream(data.getData());
            } catch (FileNotFoundException e) {
                //e.printStackTrace();
                Log.e("CCALM", "Error: ", e);
            }
            if (inputStream != null) {

                BarcodeDetector bDetector = new BarcodeDetector.Builder(ScanActivity.this)
                        .setBarcodeFormats(Barcode.QR_CODE) // set QR code as the format type
                        .build();
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                Frame frame = new Frame.Builder().setBitmap(bitmap).build();
                if (bDetector.isOperational()) {
                    final SparseArray<Barcode> barcodes = bDetector.detect(frame);
                    if (barcodes.size() == 0) {
                        Toast toast = Toast.makeText(getApplicationContext(),
                                getResources().getString(R.string.QR_code_not_found), Toast.LENGTH_LONG);
                        toast.show();
                    } else {
                        qrcode = barcodes.valueAt(0).displayValue;
                        if(qrcode.indexOf("ccalm")>=0){
                            String android_id = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
                            DataActSendTask send = new DataActSendTask(qrcode,android_id);
                            send.execute();
                        }else{
                            Toast toast = Toast.makeText(getApplicationContext(),
                                    getResources().getString(R.string.Error_QR_code)+": \""+qrcode+"\"", Toast.LENGTH_LONG);
                            toast.show();
                        }
                    }
                }
                bDetector.release();
            }
        }
    }

    public void setJSONObject(JSONObject json)
    {
        try {
            if(json.getInt("error_code")==0) {
                tvName.setText(json.getString("name"));
                tvCountry.setText(json.getString("country_name"));
                tvOrganization.setText(json.getString("company_name"));

                //Update terminals table (After that, the terminal tables will be updated using synchronization.)
                String sql="select * from terminals where id="+json.getString("id");
                boolean exists=false;
                DbOpenHelper dboh = new DbOpenHelper(this);
                SQLiteDatabase rdb = null;
                SQLiteDatabase wdb = null;
                Cursor cursor = null;
                try {
                    rdb = dboh.getReadableDatabase();
                    wdb = dboh.getWritableDatabase();
                    cursor = rdb.rawQuery(sql, null);
                    if(cursor.moveToFirst())
                    {
                        exists=true;
                    }

                    if(exists){
                        sql="update terminals set country_id=?,company_id=?,name=?,serial=? where id=?";
                        SQLiteStatement stmt = wdb.compileStatement(sql);
                        stmt.bindLong(1, json.getLong("country_id"));
                        stmt.bindLong(2, json.getLong("company_id"));
                        stmt.bindString(3, json.getString("name"));
                        stmt.bindString(4, Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID));
                        stmt.bindLong(5, json.getLong("id"));
                        stmt.executeUpdateDelete();
                    }else{
                        sql="insert into terminals(id,country_id,company_id,name,serial)values(?,?,?,?,?);";
                        SQLiteStatement stmt = wdb.compileStatement(sql);
                        stmt.bindLong(1, json.getLong("id"));
                        stmt.bindLong(2, json.getLong("country_id"));
                        stmt.bindLong(3, json.getLong("company_id"));
                        stmt.bindString(4, json.getString("name"));
                        stmt.bindString(5, Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID));
                        stmt.executeInsert();
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }finally{
                    if(cursor!=null){ cursor.close(); }
                    if(rdb!=null){ rdb.close(); }
                    if(wdb!=null){ wdb.close(); }
                }
                dboh.close();

            }else {
                String errorMessage = json.getString("errorMessage");
                if (!errorMessage.equals("")) {
                    AlertDialog alertDialog = new AlertDialog.Builder(ScanActivity.this).create();
                    alertDialog.setTitle(getResources().getString(R.string.Attention));
                    alertDialog.setMessage(errorMessage);
                    alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    });
                    //alertDialog.setIcon(R.drawable.icon);
                    alertDialog.show();
                }
                qrcode = "";
            }
        } catch (JSONException e) {
            //e.printStackTrace();
            Log.e("CCALM", "Error: ", e);
        }
    }

    private void initialiseDetectorsAndSources() {

        //Toast.makeText(getApplicationContext(), "Barcode scanner started", Toast.LENGTH_SHORT).show();

        barcodeDetector = new BarcodeDetector.Builder(this)
                .setBarcodeFormats(Barcode.QR_CODE)
                .build();

        cameraSource = new CameraSource.Builder(this, barcodeDetector)
                .setRequestedPreviewSize(800, 800)
                .setAutoFocusEnabled(true) //you should add this feature
                .build();

        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    if (ActivityCompat.checkSelfPermission(ScanActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                        cameraSource.start(surfaceView.getHolder());
                    } else {
                        ActivityCompat.requestPermissions(ScanActivity.this, new
                                String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
                    }

                } catch (IOException e) {
                    //e.printStackTrace();
                    Log.e("CCALM", "Error: ", e);
                }
            }

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

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });

        barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {

/*            private final Handler handler = null;

            public Detector.Processor<Barcode>() {
                handler = new Handler();
            }
*/
            @Override
            public void release() {
                //Toast.makeText(getApplicationContext(), "Для предотвращения утечки памяти сканер штрих-кода остановлен", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void receiveDetections(Detector.Detections<Barcode> detections) {
                final SparseArray<Barcode> barcodes = detections.getDetectedItems();
                if (barcodes.size() != 0) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {

                            if(!qrcode.equals(barcodes.valueAt(0).displayValue)) {
                                qrcode = barcodes.valueAt(0).displayValue;
                                if(qrcode.indexOf("ccalm")>=0){
                                    String android_id = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
                                    DataActSendTask send = new DataActSendTask(qrcode,android_id);
                                    send.execute();
                                }else{
                                    Toast toast = Toast.makeText(getApplicationContext(),
                                            getResources().getString(R.string.Error_QR_code)+": \""+qrcode+"\"", Toast.LENGTH_LONG);
                                    toast.show();
                                }
                            }
                        }
                    });
                }
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        cameraSource.release();
    }

    @Override
    protected void onResume() {
        super.onResume();
        initialiseDetectorsAndSources();

        //Подгоняем размер под квадран
        ViewGroup.LayoutParams params = surfaceView.getLayoutParams();
        params.height = getWindowManager().getDefaultDisplay().getWidth();
        surfaceView.setLayoutParams(params);
    }

    //Запрашиваю данные с сервера
    public class DataActSendTask extends AsyncTask<Void, Void, Void> {
        private final String mQRCode;
        private final String mAndroid_id;

        private String mErrmsg;
        private JSONObject mResult; //Результирующий JSONObject
        // mainObject = new JSONObject(Your_Sring_data);

        DataActSendTask(String qrcode,String android_id) {
            mQRCode=qrcode;
            mAndroid_id = android_id;

            mErrmsg = "";
            mResult = null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            ScanActivity.this.showProgress(true,getResources().getString(R.string.Search));
        }

        @Override
        protected Void doInBackground(Void... params) {

            //I'm trying to login using JSON string
            JSONObject data = new JSONObject();
            try {
                data.put("qrcode",mQRCode);
                data.put("android_id",mAndroid_id);
                data.put("secret",md5(mAndroid_id+"_ASDC"));
            } catch (JSONException ex) {
                ex.printStackTrace();
                mErrmsg+=ex.getLocalizedMessage()+" ";
            }

            //Trying to send a request to the server
            try {
                URL url = new URL(MySynchronizationOld.URL+"/asdc/qrcode/");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(25000);
                conn.setConnectTimeout(25000);
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
                conn.setRequestProperty("Accept", "application/json");
                conn.setRequestProperty("Accept-Charset", "UTF-8");
                conn.setDoInput(true);
                conn.setDoOutput(true);

                OutputStream os = conn.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
                writer.write(data.toString());
                writer.flush();
                writer.close();
                os.close();

                int responseCode=conn.getResponseCode();
                if (responseCode == HttpsURLConnection.HTTP_OK) {
                    String JSONStr=""; //Результирующий JSON
                    String line;
                    BufferedReader br=new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    while ((line=br.readLine()) != null) {
                        JSONStr+=line;
                    }
                    try {
                        mResult = new JSONObject(JSONStr);
                    } catch (JSONException e) {
                        mErrmsg = "JSON parsing error: "+JSONStr;
                    }
                }else{
                    mErrmsg = "Failed to get data from the server.";
                }

            } catch (UnsupportedEncodingException e) {
                mErrmsg = e.getMessage();
            } catch (IOException e) {
                mErrmsg = e.getMessage();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            ScanActivity.this.showProgress(false,"");

            if (mResult != null)
                ScanActivity.this.setJSONObject(mResult);

            if (mErrmsg != null && !mErrmsg.equals("")) {
                AlertDialog alertDialog = new AlertDialog.Builder(ScanActivity.this).create();
                alertDialog.setTitle("Error");
                alertDialog.setMessage(mErrmsg);
                alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
                //alertDialog.setIcon(R.drawable.icon);
                alertDialog.show();
            }
        }

        @Override
        protected void onCancelled() {
            ScanActivity.this.showProgress(false,"");
        }
    }

}