package my.com.pcloud.salesapplite;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Handler;
import android.util.Log;

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

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Set;
import java.util.UUID;

/**
 * Created by han on 10/23/15.
 */
public class print_order {

    Context this_context;



    BluetoothAdapter mBluetoothAdapter;
    BluetoothSocket mmSocket;
    BluetoothDevice mmDevice;


    OutputStream mmOutputStream;
    InputStream mmInputStream;
    Thread workerThread;
    private int yr, mon, dy;
    private int hr, min, sec;


    String this_time_stamp;

    byte[] readBuffer;
    int readBufferPosition;
    int counter;
    boolean stopWorker;

    String setting_company_name;
    String setting_company_address;
    String setting_document_title;

    String setting_printer_name="";
    String setting_paper_cutting="";
    String setting_printer_size="80MM";

    String setting_open_drawer;
    String setting_gst;



    SQLiteDatabase posDB;
    SQLiteDatabase tranDB;


    String active_user_full_name="";
    String active_user_name="";

    String setting_show_customer_gst="";
    String setting_show_customer_billing_address="";
    String setting_show_customer_delivery_address="";
    String setting_show_gst_summary="";

    String setting_show_product_code="";
    String setting_show_product_barcode="";
    String setting_show_product_name="";


    String setting_footer_remark="";


    String setting_printing_format_item="";

    String setting_operation_mode="";
    String this_invoice_operation_mode="";


    String set_gst_computation;
    float set_gst_percentage=0F;



    public print_order(Context context) {

        this_context = context;


        setting_printer_name = "InnerPrinter";




        findBT();
    }



    public void print(JSONObject jObject_Order){

        try {



            if(mmSocket.isConnected()) {
                Log.d("BT", "Connected" );

                sendData(jObject_Order);
            }
            else {

                Log.d("BT", "Disconnected, re-connect" );
                closeBT();
                openBT();
                sendData(jObject_Order);
            }







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

        } catch (IOException ex) {

            ex.printStackTrace();
        }


    }




    // This will find a bluetooth printer device
    void findBT() {

        Log.d("BT", "Find BT");
        try {
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

            if (mBluetoothAdapter == null) {
                //myLabel.setText("No bluetooth adapter available");
                Log.d("BT", "No Adapter" );
            }

            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableBluetooth = new Intent(
                        BluetoothAdapter.ACTION_REQUEST_ENABLE);
                //startActivityForResult(enableBluetooth, 0);

                Log.d("BT", "Bluetooth Not Enabled");
            }

            Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
            if (pairedDevices.size() > 0) {
                for (BluetoothDevice device : pairedDevices) {


                    Log.d("BT", "Finding Device..."+device.getName().toString());

                    // MP300 is the name of the bluetooth printer device
                    if (device.getName().equals(setting_printer_name)) {
                        mmDevice = device;



                        Log.d("BT", "Device Selected");
                        break;

                    }



                }
            }

            Log.d("BT", "Device Found");


            //myLabel.setText("Bluetooth Device Found");
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    // Tries to open a connection to the bluetooth printer device
    void openBT() throws IOException {
        try {


            Log.d("BT", "Trying Connection");

            //BluetoothDevice mmDevice = mBluetoothAdapter.getRemoteDevice(btdevaddr);

            // Standard SerialPortService ID
            UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
            mmSocket = null;

            Method m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
            mmSocket = (BluetoothSocket) m.invoke(mmDevice, 1);
            mmSocket.connect();

            Log.d("BT", "Connection Established");


            //mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
            //mmSocket.connect();
            Log.d("BT", "Device Socket Established");


            mmOutputStream = mmSocket.getOutputStream();
            //mmInputStream = mmSocket.getInputStream();

            //beginListenForData();
            //Log.d("BT", "Device Listening to data");



        } catch (NullPointerException e) {
            e.printStackTrace();
            Log.d("BT", "Fail open Device Socket",e);

        } catch (Exception e) {
            e.printStackTrace();
            Log.d("BT", "Fail open Device Socket",e);
        }
    }

    void beginListenForData() {
        try {
            final Handler handler = new Handler();

            // This is the ASCII code for a newline character
            final byte delimiter = 10;

            stopWorker = false;
            readBufferPosition = 0;
            readBuffer = new byte[1024];

            workerThread = new Thread(new Runnable() {
                public void run() {
                    while (!Thread.currentThread().isInterrupted()
                            && !stopWorker) {

                        try {

                            int bytesAvailable = mmInputStream.available();
                            if (bytesAvailable > 0) {
                                byte[] packetBytes = new byte[bytesAvailable];
                                mmInputStream.read(packetBytes);
                                for (int i = 0; i < bytesAvailable; i++) {
                                    byte b = packetBytes[i];
                                    if (b == delimiter) {
                                        byte[] encodedBytes = new byte[readBufferPosition];
                                        System.arraycopy(readBuffer, 0,
                                                encodedBytes, 0,
                                                encodedBytes.length);
                                        final String data = new String(
                                                encodedBytes, "US-ASCII");  //UTF-8, US-ASCII, GB18030
                                        readBufferPosition = 0;

                                        handler.post(new Runnable() {
                                            public void run() {
                                                // myLabel.setText(data);
                                            }
                                        });
                                    } else {
                                        readBuffer[readBufferPosition++] = b;
                                    }
                                }
                            }

                        } catch (IOException ex) {
                            stopWorker = true;
                        }

                    }
                }
            });

            workerThread.start();
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * This will send data to be printed by the bluetooth printer
     */
    void sendData(JSONObject jObject_Order) throws IOException {
        try {

            // the text typed by the user
            Log.d("BT", "Device Printing Started");

            String msg = "";



            setting_printer_size="58MM";


            if(mmSocket.isConnected()) {





                int margin_1_left = 0;
                int margin_1_right = 0;

                int margin_2_left = 0;
                int margin_2_right = 0;

                int margin_3_left = 0;
                int margin_3_center = 0;
                int margin_3_right = 0;

                int margin_4_left = 0;
                int margin_4_right = 0;


                String separator_line = "";


                if (setting_printer_size.equals("58MM")) {


                    margin_1_left = 10;
                    margin_1_right = 22;

                    margin_2_left = 20;
                    margin_2_right = 12;

                    margin_3_left = 17;
                    margin_3_center = 7;
                    margin_3_right = 8;

                    margin_4_left = 24;
                    margin_4_right = 8;

                    separator_line = "--------------------------------"; //32 char


                } else {

                    margin_1_left = 15;
                    margin_1_right = 27;

                    margin_2_left = 20;
                    margin_2_right = 22;

                    margin_3_left = 22;
                    margin_3_center = 10;
                    margin_3_right = 10;

                    margin_4_left = 27;
                    margin_4_right = 15;


                    separator_line = "------------------------------------------"; //42 char


                }


                //======Company Name================================================

                //align to center
                mmOutputStream.write(0x1B);
                mmOutputStream.write("a".getBytes("GB18030"));
                mmOutputStream.write(0x01);

                //Double Size Text
                mmOutputStream.write(0x1B);
                mmOutputStream.write("!".getBytes("GB18030"));
                mmOutputStream.write(0x39);


                mmOutputStream.write("Allunique".getBytes("GB18030"));

                //Normal Size Text
                mmOutputStream.write(0x1B);
                mmOutputStream.write("!".getBytes("GB18030"));
                mmOutputStream.write(0x00);

                //Next Line
                mmOutputStream.write("\n".getBytes("GB18030"));

                //align back to left
                mmOutputStream.write(0x1B);
                mmOutputStream.write("a".getBytes("GB18030"));
                mmOutputStream.write(0x00);

                //========Address===================================
                //align to center
                mmOutputStream.write(0x1B);
                mmOutputStream.write("a".getBytes("GB18030"));
                mmOutputStream.write(0x01);
                //String lines[] = String.split("\\r?\\n");


                /*
                String[] address_array = setting_company_address.split("\\n");


                for (int i = 0; i < address_array.length; i++) {

                    mmOutputStream.write(address_array[i].getBytes("GB18030"));
                    mmOutputStream.write("\n".getBytes("GB18030"));
                }

                */


                //align back to left
                mmOutputStream.write(0x1B);
                mmOutputStream.write("a".getBytes("GB18030"));
                mmOutputStream.write(0x00);

                mmOutputStream.write("\n".getBytes("GB18030"));

                //=======Doc Title====================================
                //align to center
                mmOutputStream.write(0x1B);
                mmOutputStream.write("a".getBytes("GB18030"));
                mmOutputStream.write(0x01);

                //Double Size Text
                mmOutputStream.write(0x1B);
                mmOutputStream.write("!".getBytes("GB18030"));
                mmOutputStream.write(0x39);


                mmOutputStream.write("INVOICE".getBytes("GB18030"));

                //Normal Size Text
                mmOutputStream.write(0x1B);
                mmOutputStream.write("!".getBytes("GB18030"));
                mmOutputStream.write(0x00);

                //Next Line
                mmOutputStream.write("\n".getBytes("GB18030"));
                mmOutputStream.write("\n".getBytes("GB18030"));

                //align back to left
                mmOutputStream.write(0x1B);
                mmOutputStream.write("a".getBytes("GB18030"));
                mmOutputStream.write(0x00);


                String order_amount="0.00";


                //------------------ Header-----------------------------------------------
                JSONArray jArray_content_document = jObject_Order.getJSONArray("document_header");

                for (int i=0; i < jArray_content_document.length(); i++)
                {

                    try {
                        JSONObject oneObject = jArray_content_document.getJSONObject(i);


                        String order_id = oneObject.getString("doc_no");
                        String order_date = oneObject.getString("date");

                        order_amount = oneObject.getString("amount");




                        mmOutputStream.write(padRight("Doc No.", margin_1_left).getBytes("GB18030"));
                        mmOutputStream.write(padRight(": " + order_id, margin_1_right).getBytes("GB18030"));
                        mmOutputStream.write("\n".getBytes("GB18030"));



                        mmOutputStream.write(padRight("Date", margin_1_left).getBytes("GB18030"));
                        mmOutputStream.write(padRight(": " + order_date, margin_1_right).getBytes("GB18030"));
                        mmOutputStream.write("\n".getBytes("GB18030"));




                    } catch (JSONException e) {
                        Log.d("GetDocument","JSON Error"+e);
                    }
                }




                mmOutputStream.write("\n".getBytes("GB18030"));



                mmOutputStream.write(separator_line.getBytes("GB18030"));
                mmOutputStream.write("\n".getBytes("GB18030"));



                mmOutputStream.write(padRight("Product", margin_4_left).getBytes("GB18030"));
                mmOutputStream.write(padRight("Amt", margin_4_right).getBytes("GB18030"));
                mmOutputStream.write("\n".getBytes("GB18030"));


                mmOutputStream.write(separator_line.getBytes("GB18030"));
                mmOutputStream.write("\n".getBytes("GB18030"));



                //------------------ Item-----------------------------------------------
                JSONArray jArray_content_item = jObject_Order.getJSONArray("document_item");

                for (int i=0; i < jArray_content_item.length(); i++)
                {

                    try {
                        JSONObject oneObject = jArray_content_item.getJSONObject(i);

                        String product_code = oneObject.getString("code");
                        String product_name = oneObject.getString("name");
                        String amount = oneObject.getString("amount");



                        mmOutputStream.write(padRight(product_name, margin_4_left).getBytes("GB18030"));
                        mmOutputStream.write(padLeft(amount, margin_4_right).getBytes("GB18030"));
                        mmOutputStream.write("\n".getBytes("GB18030"));



                        mmOutputStream.write(("Code: "+product_code).getBytes("GB18030"));
                        mmOutputStream.write("\n".getBytes("GB18030"));




                    } catch (JSONException e) {
                        Log.d("GetDocument","JSON Error"+e);
                    }
                }




                mmOutputStream.write(separator_line.getBytes("GB18030"));
                mmOutputStream.write("\n".getBytes("GB18030"));



                mmOutputStream.write(padRight("Total Amount", margin_4_left).getBytes("GB18030"));
                mmOutputStream.write(padLeft(order_amount, margin_4_right).getBytes("GB18030"));



                mmOutputStream.write(separator_line.getBytes("GB18030"));
                mmOutputStream.write("\n".getBytes("GB18030"));



                Calendar c = Calendar.getInstance();

                yr = c.get(Calendar.YEAR);
                mon = c.get(Calendar.MONTH);
                dy = c.get(Calendar.DAY_OF_MONTH);

                hr = c.get(Calendar.HOUR_OF_DAY);
                min = c.get(Calendar.MINUTE);
                sec = c.get(Calendar.SECOND);


                this_time_stamp = yr + "-" + String.format("%02d", mon + 1) + "-" + String.format("%02d", dy) + " ";
                this_time_stamp = this_time_stamp + String.format("%02d", hr + 0) + ":" + String.format("%02d", min + 0) + ":" + String.format("%02d", sec) + " ";

                mmOutputStream.write("\n".getBytes("GB18030"));
                mmOutputStream.write("Printed on: ".getBytes("GB18030"));
                mmOutputStream.write(this_time_stamp.getBytes("GB18030"));
                mmOutputStream.write("\n".getBytes("GB18030"));

                if (active_user_full_name.equals("")) {


                } else {
                    mmOutputStream.write(active_user_full_name.getBytes("GB18030"));
                    mmOutputStream.write("\n".getBytes("GB18030"));

                }

                msg="";
                //msg += "\n";
                //msg += "\n";
                //msg += "\n";
                //msg += "\n";



                //additional line feed base on system settting

                msg += "\n";
                msg += "\n";




                //mmOutputStream.write(msg.getBytes("GB18030"));
                mmOutputStream.write(msg.getBytes("UTF-8"));





/*
                if (setting_paper_cutting.equals("YES")) {
                    //cut paper
                    mmOutputStream.write(0x00);
                    mmOutputStream.write(0x1D);
                    mmOutputStream.write(0x56);
                    mmOutputStream.write(0x01);
                    mmOutputStream.write(0x00);
                }

*/






                Log.d("BT", "Device Printing Finished");



                mmOutputStream.flush();





                Log.d("BT", "Device Printing Finished");



            }
            else
            {

                Log.d("BT", "Device isConnected = False");

            }



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




    // Close the connection to bluetooth printer.
    void closeBT() throws IOException {
        try {
            Log.d("BT", "Device Closing Bluetooth Socket");


            Log.d("BT", "SocketStatus: " + mmSocket.isConnected());

            stopWorker = true;

            mmOutputStream.close();

            // mmInputStream.close();

            mmSocket.close();

            Log.d("BT", "SocketStatus: " + mmSocket.isConnected());

            Log.d("BT", "Device Closed Bluetooth Socket");

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

        } catch (Exception e) {

            e.printStackTrace();
        }
    }




    public static String wrapString(String s, String deliminator, int length) {
        String result = "";
        int lastdelimPos = 0;
        for (String token : s.split(" ", -1)) {
            if (result.length() - lastdelimPos + token.length() > length) {
                result = result + deliminator + token;
                lastdelimPos = result.length() + 1;
            }
            else {
                result += (result.isEmpty() ? "" : " ") + token;
            }
        }
        return result;
    }


    public static String padRight_Chinese(String s, int n) {

        int text_length=0;

        final byte[] utf8Bytes;
        try {
            utf8Bytes = s.getBytes("GB18030");
            text_length = utf8Bytes.length;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }


        String padding_text="";
        int pad_n = n - text_length;
        if(pad_n>0) {
            padding_text = new String(new char[pad_n]).replace("\0", " ");
        }
        return s+padding_text;

    }

    public static String padRight(String s, int n) {
        return String.format("%1$-" + n + "s", s);
    }

    public static String padLeft(String s, int n) {
        return String.format("%1$" + n + "s", s);
    }

}
