package beyondsoft.bewomitarbeiterapp;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.IntentCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.text.Html;
import android.text.format.DateFormat;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

/**
 * Created by bib on 03.05.2016.
 */
public class ChatActiviti extends ActionBarActivity{

    //View Variablen
    protected TextView chat;
    protected EditText text;
    protected Button senden;

    //Server Variablen
    public static Socket socket;
    protected static final String dstAddress = "192.168.1.115"; //10.0.2.2"
    protected static final  int dstPort = 5000;
    DataOutputStream st;

    String SaveCompletteMS;

    BufferedReader in = null;

    //Design View
    protected ListView listView;
    protected boolean isMe = true;
    protected List<ChatMessageFormat> chatMessages;
    protected ArrayAdapter<ChatMessageFormat> adapter;
    ChatMessageFormat chatMessage;


    Thread currentlisten;

    //Save/ Load Variblen
    File file;
    File Unsendfile = null;
    //Chat Name
    protected String name;


    //Für Notification
    private static boolean isOnStop = false;

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

        //########### Custom Action Bar ##################################
        ActionBar action = getSupportActionBar();

        action.setDisplayShowHomeEnabled(false);
        action.setDisplayShowTitleEnabled(false);

        LayoutInflater inflate = LayoutInflater.from(this);
        View mCustomView = inflate.inflate(R.layout.custom_menuebar,null);


        // Initialiesiere die Variablen
        TextView titlename = (TextView)mCustomView.findViewById(R.id.PersonalName);
        ImageView titlepic = (ImageView)mCustomView.findViewById(R.id.PersonalPic);

        //get Daten aus vorheriger Activity
        Bundle zielkorb = getIntent().getExtras();
        name  = zielkorb.getString("Name");

        byte[] bildArray  = zielkorb.getByteArray("Bild");
        Bitmap customerImage;

        //ein try catch wäre vorteilhaft || Später
        if(bildArray != null) {
            customerImage = BitmapFactory.decodeByteArray(bildArray, 0, bildArray.length);
            titlepic.setImageBitmap(GetCircleBitmap(customerImage));
        }

        //Online Status listener
       /* ImageView img = (ImageView) mCustomView.findViewById(R.id.status);
        img.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ChatActiviti.this.openOptionsMenu(); // activity's onCreateOptionsMenu gets called
                //optionsMenu.performIdentifierAction(R.id., 0);
            }
        });*/




        titlename.setText(name);

        action.setCustomView(mCustomView);
        action.setDisplayShowCustomEnabled(true);
        //###########################################################################################

        senden = (Button)findViewById(R.id.Sendebutton);
        //chat = (TextView)findViewById(R.id.ChatText);

        //################### Initial Design Variabeln Message Adapter #############################################
        chatMessages = new ArrayList<>();

        listView = (ListView)findViewById(R.id.list_msg);

        adapter = new MessageAdapter(this, R.layout.item_chat_left,chatMessages);
        listView.setAdapter(adapter);

        //############################ Initial Design Variablen ende ###############################

        //########################### Initial Socket ###############################################
        try {
            MainActivityMitarbeiter.isThreadPause = true;

            socket = MainActivityMitarbeiter.socket;

            in = MainActivityMitarbeiter.in;
            //nachricht an server senden welcher name jetz aktiv connected ist
            st = new DataOutputStream(socket.getOutputStream());
        }catch(Exception e){/*Fail*/}


       // MainActivityMitarbeiter.listen.interrupt();
       // MainActivityMitarbeiter.listen = null;



        //##########################################################################################

        //############## Safe / Write gedöns #########################################################
        CreateFile();

        ReadMessageToStorage();

        //##########################################################################################


        //Öffnet eine Verbindung zum Server
    //    new Thread(new OpenConnection()).start();


        text = (EditText)findViewById(R.id.editText);

        //Sendet eine Nachricht an den Server/Clienten
        senden.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //isMe = true;

                if(text.getText().toString().equals("exit")){
                    //eine möglich keit die connection zu schließen
                   // new Thread(new ConnectionClose()).start();
                }else if(!text.getText().toString().equals("")){
                    new Thread(new SendMS()).start();
                }else{
                    Toast.makeText(ChatActiviti.this, "Sie müssen schon Text eingeben ", Toast.LENGTH_SHORT).show();
                }

            }
        });


        //Erstelle einen immer horchenden Listener
        Thread t = new Thread(new SocketListener());
        t.start();



        //MainActivityMitarbeiter.listen.sus
    }


//######################### Server/ Client gedöns ##################################################
    /*public class OpenConnection implements Runnable{
        public void run(){
            try {
                socket = new Socket(dstAddress,dstPort);
                //  Log.v("Status: ","Vorhanden 3");

                //nachricht an server senden welcher name jetz aktiv connected ist
                st = new DataOutputStream(socket.getOutputStream());
                name=name+"/1";
                byte[] ts = name.getBytes();
                st.write(ts);
                st.flush();

            } catch (Exception e) {
               // e.printStackTrace();
                Log.v("Connection: ","Konnte nicht Aufgebaut");
                 socket = null;
                //methode zur abfrage

            }
        }
    }*/

    public class SendMS implements Runnable{
        public void run(){
            String al = text.getText().toString();



            byte[] ts = al.getBytes();
            try{
                if(socket!= null ) {

                    //try catch bei catch SaveAfterLoseConnection();



                    st.write(ts);
                    st.flush();
                }


                listView.post(new Runnable() {
                    @Override
                    public void run() {
                        Calendar c = Calendar.getInstance();
                        SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
                        String formattedDate = df.format(c.getTime());

                        SaveCompletteMS = text.getText().toString()+"/"+isMe+"%"+formattedDate+"\n";

                            WriteMessagesfromStorage(text.getText().toString()+"/"+isMe+"%"+formattedDate+"\n");

                            chatMessage = new ChatMessageFormat(text.getText().toString(), isMe, formattedDate);
                            chatMessages.add(chatMessage);
                            adapter.notifyDataSetChanged();

                            text.setText("");

                    }
                });
            }catch(IOException s){
                Log.v("Status: ","Senden einer Nachricht konnte nicht ausgeführt werden. Save wird ausgeführt");
                //Log.v("hallo",);


                SaveAfterLoseConnection(SaveCompletteMS);
                s.printStackTrace();
            }
        }
    }

   /* public class ConnectionClose implements Runnable{
        public void run(){
            try {
               // Log.v("Bin ich Überhaupt", "Hier drinne");
                if (st != null) {
                    st.flush();
                    st.close();
                }
                if (socket != null)
                    socket = null;
                //    Log.v("Schliesen :","?? Möglich");
               // }
                Log.v("Status","Socket succesfull closed");
            }catch(IOException se){
                Log.v("Status: ","Schließen nicht möglich. Es ist ein Fehler aufgetreten");
            }
        }
    }*/

    // Erhalte Messages all the time
    public class SocketListener implements Runnable{


        String str;
        long i = 1;
        //BufferedReader in = null;
        public void run(){
            try{
                //DesignTechnische gründe
                Log.v("Komme","ICh den Rein");
                while(true){

                        if (socket != null) {
                            Log.v("Komme","So wie es aussieht nicht ");
                            if(socket.isConnected()) {
                                Log.v("Connection Steht ", "Connection Steht");
                                Log.v("Komme","So wie es aussieht nicht2 ");
                                //final TextView text = (TextView)findViewById(R.id.ChatText);

                                final ListView listV = (ListView) findViewById(R.id.list_msg);

                                Log.v("Komme","So wie es aussieht nicht 3");
                               // in = new BufferedReader(new InputStreamReader(MainActivityMitarbeiter.socket.getInputStream()));

                              /*---> da wird das pendant ausgeführt und nicht dieses */  String s = in.readLine();
                                Log.v("Komme","So wie es aussieht nicht 4");
                                CharSequence cs = text.getText();

                                // wir nehmen mal cs raus
                                //str = cs + "\r\n" + s;
                                str = s;

                                if (s == null)
                                    break;

                                //Design Spezifisch
                                listV.post(new Runnable() {
                                    @Override
                                    public void run() {

                                        Calendar c = Calendar.getInstance();
                                        SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
                                        String formattedDate = df.format(c.getTime());

                                        boolean determind = false;

                                        WriteMessagesfromStorage(str+"/"+determind+"%"+formattedDate+"\n");

                                        chatMessage = new ChatMessageFormat(str, determind, formattedDate);
                                        chatMessages.add(chatMessage);
                                        adapter.notifyDataSetChanged();

                                        Log.v("","");

                                        if(isOnStop == true){
                                            SetNotifi("Bärtiger Hanz",str);
                                        }

                                    }
                                });

                                i++;
                            }
                        } else {

                            if (in != null)
                                in.close();
                        }

                  //  else Log.v("Connection","nicht aufgebaut"); nach tausend versuchen break und fehler ausgabe

                }

            }catch(Exception e){
                Log.v("Status ","Verbindung zum Server wurde seitens dem Server getrennt ");
               // Log.e(getClass().getName(),e.getMessage());
               // e.printStackTrace();
            }
        }
    }
//#################################### Server Client Ende ##########################################

    //########################### Speichere Message für Server bei unsend #####################################
    public void SaveAfterLoseConnection(String UnsendMessage){
        CreateCustomFileForUnSendMessage();
        try{
            FileOutputStream stream = new FileOutputStream(Unsendfile,true);

            try{
                stream.write(UnsendMessage.getBytes());
            }finally {
                stream.close();
            }
        }catch (Exception e){
            Log.v("Fehler",e.getMessage());
        }
    }

    public void SendAfterGetConnection(){

        //ist eine UnsendMessage File vorhanden
        if(Unsendfile != null && socket.isConnected()){
            try{
                    FileInputStream stream = new FileInputStream(Unsendfile);
                    InputStreamReader in = new InputStreamReader(stream);
                    BufferedReader readLn = new BufferedReader(in);

                    String line = readLn.readLine();
                    String allLines="";

                    while (line != null) {
                        allLines += line;

                        String[] splitt = line.split("/");

                        if(splitt.length >1 ) {
                            String[] ArtDate = splitt[1].split("%");

                            final String message = splitt[0];
                            final boolean art = Boolean.valueOf(ArtDate[0]);
                            final String datetime = ArtDate[1];

                            //für jede Gelesene Line Sende Nachricht
                            new Thread(new SendUnsendMS(message)).start();
                        }
                        line = readLn.readLine();
                    }
                    stream.close();
                    in.close();
                Unsendfile.delete();
            }catch(Exception fe){
                Log.v("Status","Ein problem ist im BEreich Unsend Ms Aufgetreten");
            }
            //recreate();
        }
    }

    public class SendUnsendMS implements Runnable{

        String al;

        SendUnsendMS(String unMS){
            this.al = unMS;
        }

        public void run() {
            //String al = text.getText().toString();

            byte[] ts = al.getBytes();
            try {
                if (socket != null && st != null) {

                    //try catch bei catch SaveAfterLoseConnection();
                    st.write(ts);
                    st.flush();
                }
            }catch(Exception xs){

            }
        }
    }

    public void CreateCustomFileForUnSendMessage(){
        try{
            File pfad = getBaseContext().getFilesDir();

            //Für external Save
            //File pfad = getBaseContext().getExternalFilesDir(null);

            //Erstelle das File Objekt
            Unsendfile = new File(pfad,name+"_Unsend"+".txt");

        }catch(Exception e){
            Log.v("Fehler"," Das erstellen/öffnen einer Datei ist Derzeit nicht möglich");
        }
    }

    //####################### Ende Unsend Message Gedöns ###########################################



    //############### Menue Bereich ################################################################

    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menue_chat, menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
            case R.id.action_delet_Storage:
                file.delete(); //Delet aktuell gespeicherte message
                recreate(); // ---> gegebenenfals umändern, aber fürs erste reichts
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

  //################################################################################################


    //############## Setze Notification ############################################################

    public void SetNotifi(String Username,String message){

        //Convertiert in Pic Resource in ein Bitmap
        //BitmapFactory.decodeResource(getResources(), R.drawable.bslogo)

        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this)
                        .setSmallIcon(R.drawable.bslogo)
                        .setContentTitle(Username)
                        .setContentText(message)
                        .setAutoCancel(true)
                        //ab hier neuland
                        .setDefaults(Notification.DEFAULT_SOUND)
                        .setVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 }) //Notification.Default_Vibrate
                        .setLights(Color.YELLOW, 3000, 3000)  //Notification.Default_Lights
                        .setOngoing(true);
                        //neuland ende

        Intent resultIntent = new Intent(this, ChatActiviti.class);
        //versuch ab hier neuland
        resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        //neuland ende
        PendingIntent resultPendingIntent =
                PendingIntent.getActivity(
                        this.getApplicationContext(),
                        0,
                        resultIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT

                );
        NotificationManager mNotifyMgr =
                (NotificationManager) getSystemService(NOTIFICATION_SERVICE);


        mBuilder.setContentIntent(resultPendingIntent);

        mNotifyMgr.notify(001, mBuilder.build());
    }

    //##############################################################################################


    //################ Activit abfragen ############################################################
    public void onResume() {
       // Log.v("Stuss","Hier nochmals on creat aufrufen");
        isOnStop = false;

        MainActivityMitarbeiter.isThreadPause = true;

        super.onResume();
    }

    public void onStop(){
      //  Thread t = new Thread(new ConnectionClose());
      //  t.start();

        MainActivityMitarbeiter.isThreadPause = false;

        isOnStop = true;
        super.onStop();
    }

    public void onDestroy(){
       // Thread t = new Thread(new ConnectionClose());
       // t.start();
      //  currentlisten = null;
        MainActivityMitarbeiter.isThreadPause = false;

        super.onDestroy();
    }
    //##############################################################################################

    //################# Lade/Speichere Die Messages ################################################
    //create a File
    public void CreateFile(){

          try{

                File pfad = getBaseContext().getFilesDir();

                //Für external Save
                //File pfad = getBaseContext().getExternalFilesDir(null);

                //Erstelle das File Objekt
                 //file = new File(pfad,name+".txt");

                  //vorläufig ##### für debug zwecke
                  file = new File(pfad,"demo"+".txt");
          }catch(Exception e){
                  Log.v("Fehler"," Das erstellen/öffnen einer Datei ist Derzeit nicht möglich");
          }
    }


    //Internal Storage
    public void WriteMessagesfromStorage(String message){
        try{
            FileOutputStream stream = new FileOutputStream(file,true);

            try{
                stream.write(message.getBytes());
            }finally {
                stream.close();
            }

           // Log.v("Status","Text: "+message+" wurde gespeichert." );

        }catch (Exception e){
            Log.v("Fehler 1 ",e.getMessage());
        }
    }

    //Internal storage
    public void ReadMessageToStorage(){
        try{

           // Log.v("Status","Verbindung steht 1");
            int lenght = (int) file.length();

            byte[] bytes = new byte[lenght];

            FileInputStream stream = new FileInputStream(file);


           // Log.v("Status","Verbindung steht 2");
            InputStreamReader in = new InputStreamReader(stream);

            BufferedReader readLn = new BufferedReader(in);

            String line = readLn.readLine();
            String allLines="";
            //Build a readLine konstrukt
            while (line != null) {
                allLines += line;

                //Funktion für das korrekte anzeigen der Geladenen Nachrichten hier implementieren
                //--->    <---//
                //String[] splitt = line.split("/");

             //   Log.v("Status",line);

                String[] splitt = line.split("/");

                if(splitt.length >1 ) {
                    String[] ArtDate = splitt[1].split("%");   //<------------ im code sind als seperator ? gesetzt // lösung einfach alle löschen und neuen chat speichern !!

                    final String message = splitt[0];

                    final boolean art = Boolean.valueOf(ArtDate[0]);

                    final String datetime = ArtDate[1];

                    listView.post(new Runnable() {
                        @Override
                        public void run() {
                            chatMessage = new ChatMessageFormat(message, art, datetime);
                            chatMessages.add(chatMessage);
                            adapter.notifyDataSetChanged();
                        }
                    });
                }

                line = readLn.readLine();


            }

            stream.close();
            in.close();

         //   Log.v("Local Storage",allLines);

        }catch(Exception e){
            Log.v("Fehler 2 ",e.getMessage());
            e.printStackTrace();
        }


    }

    //##############################################################################################

    //################# Convert Bitmap for a circled bitmap ########################################
    private Bitmap GetCircleBitmap(Bitmap bitmap) {

        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

         int color = Color.RED;
         Paint paint = new Paint();
         Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
         RectF rectF = new RectF(rect);

        //bis hierhin war alles final
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawOval(rectF, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        bitmap.recycle();

        return output;
    }
    //##############################################################################################


}
