package com.nestforce.apps.remotedroid;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.telephony.SmsManager;
import android.util.Log;
import android.widget.Toast;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class SMSUtils {

    private Context mContext;
    private int lastSentSMSStatus;

    public SMSUtils(Context mContext) {
        this.mContext = mContext;
    }


    public List<HashMap<String, String>> getThreadList(){
        Uri SMS_INBOX = Uri.parse("content://sms/conversations/");
        Cursor c = mContext.getContentResolver().query(SMS_INBOX, null, null, null, "date desc");

        List<HashMap<String,String>> threads = new ArrayList<HashMap<String, String>>();

        c.moveToFirst();
        for (int i = 0; i < c.getCount(); i++) {
            String msgCount = c.getString(c.getColumnIndexOrThrow("msg_count"));
            String threadId = c.getString(c.getColumnIndexOrThrow("thread_id"));
            String snippet = c.getString(c.getColumnIndexOrThrow("snippet"));
            String date = "";
            String address = getThreadAddress(Integer.parseInt(threadId));

            ContactsUtil mContacts = new ContactsUtil(mContext);
            String id = mContacts.getContactId(address);

            String name = address;
            if (!(id == null)) {
                HashMap<String, String> contact = mContacts.getContactById(Integer.parseInt(id));
                name = contact.get("name");
            }

            HashMap<String, String> currThread = new HashMap<String, String>();
            currThread.put("address",address);
            currThread.put("date",date); //timestamp
            currThread.put("name", name);
            currThread.put("snippet",snippet);
            currThread.put("contact_id",id);
            currThread.put("msgcount", msgCount);
            currThread.put("thread_id", threadId);
            threads.add(currThread);


            c.moveToNext();
        }
        c.close();

        return threads;
    }

    private HashMap<String,String> getThreadInfo(){
        //TODO: vai retornar datahora da ultima mensagem e nr de mensagens por ler
        return null;
    }

    private List<HashMap<String,String>> getMessages(String where, String[] whereArgs, int limitStart, int limitEnd){
        Uri uri = Uri.parse("content://sms");

        Cursor c = mContext.getContentResolver().query(uri,
                null,
                where,
                whereArgs,
                "date desc LIMIT "+String.valueOf(limitStart)+", "+String.valueOf(limitEnd)
        );
        List<HashMap<String,String>> ret = new ArrayList<HashMap<String, String>>();
        if (c.getCount() > 0){
            c.moveToLast();
            for (int i = 0; i < c.getCount(); i++) {
                String msgId = c.getString(c.getColumnIndex("_id"));
                String address = c.getString(c.getColumnIndex("address")); // phone #
                String date = c.getString(c.getColumnIndex("date"));
                String body = c.getString(c.getColumnIndex("body"));
                //String seen = c.getString(c.getColumnIndex("read"));
                String type = c.getString(c.getColumnIndex("type"));
                int thread = c.getInt(c.getColumnIndexOrThrow("thread_id"));

                ContactsUtil mContacts = new ContactsUtil(mContext);
                String contactId = mContacts.getContactId(address);

                String name = address;
                if (!(contactId == null)) {
                    HashMap<String, String> contact = mContacts.getContactById(Integer.parseInt(contactId));
                    name = contact.get("name");
                }

                HashMap<String,String> currMsg = new HashMap<>();
                currMsg.put("address",address);
                currMsg.put("name",name);
                currMsg.put("date",date); //timestamp
                currMsg.put("content",body);
                currMsg.put("contact_id",contactId);
                currMsg.put("type",type);
                currMsg.put("msg_id", msgId);
                currMsg.put("thread_id", String.valueOf(thread));

                ret.add(currMsg);
                c.moveToPrevious();
            }
        }
        return ret;
    }

    private List<HashMap<String,String>> getMessages(String where, String[] whereArgs){
        return getMessages(where,whereArgs,0,20);
    }

    public List<HashMap<String,String>> getUnreadMessages(int thread_id){
        String where = "thread_id = ? AND read = 0";
        String[] whereArgs = new String[]{String.valueOf(thread_id)};
        return getMessages(where,whereArgs);
    }

    public List<HashMap<String,String>> getUnreadMessages(){
        String where = "read = 0";
        return getMessages(where,null);
    }

    private String getThreadAddress(int thread_id){
        /*Gets the phone address from thread*/
        Uri uri = Uri.parse("content://sms");
        String where = "thread_id="+thread_id;
        Cursor c = mContext.getContentResolver().query(uri, null, where ,null,null);

        String ret = "";
        if (c.getCount() > 0) {
            c.moveToFirst();
            ret = c.getString(c.getColumnIndexOrThrow("address"));
        }
        c.close();

        return ret;
    }

    public List<HashMap<String,String>> getThreadMessages(int thread_id, int limitStart, int limitEnd){
        String where = "thread_id= ?";
        String[] whereArgs = new String[]{String.valueOf(thread_id)};

        return getMessages(where,whereArgs, limitStart, limitEnd);
    }

    public List<HashMap<String,String>> getThreadMessages(int thread_id){
        return getThreadMessages(thread_id, 0, 10);
    }

    public List<HashMap<String,String>> getThreadMessagesByAddress(String address, int limitStart, int limitEnd){
        //BUGGY: address must be exactly equal to the one in the androids database
        String where = "address= ?";
        Log.d(Utils.APP_IDENTIFIER,"SMSUtil -> getThreadMessagesByAddress ADDRESS=".concat(address));
        String[] whereArgs = new String[]{address};
        return getMessages(where,whereArgs, limitStart, limitEnd);
    }

    public List<HashMap<String,String>> getThreadMessagesByAddress(String address){
        return getThreadMessagesByAddress(address, 0, 10);
    }

    public List<HashMap<String,String>> getThreadMessagesByContactID(int contactID, int limitStart, int limitEnd){
        int threadID = getThreadIDByContactID(contactID);
        if (threadID > -1){
            return getThreadMessages(threadID, limitStart, limitEnd);
        }

        return null;
    }

    public List<HashMap<String,String>> getThreadMessagesByContactID(int contactID){
        return getThreadMessagesByContactID(contactID, 0, 10);
    }

    private int getThreadIDByContactID(int contactID){
        //Its not an elegant solution but I don't know other way to do it
        /*
            1 - Get the thread list
            2 - Check if any thread matches the contactId
            2.1 - Return the thread ID
            3 - If no thread found return -1
         */
        String pContactID = String.valueOf(contactID);
        List<HashMap<String, String>> threadList = getThreadList();
        for (int i = 0; i < threadList.size(); i++){
            HashMap<String, String> thread = threadList.get(i);
            String contact_id = thread.get("contact_id");
            if (contact_id != null){
                if (contact_id.equals(pContactID)){
                    return Integer.parseInt(thread.get("thread_id"));
                }
            }
        }

        return -1; //nothing found
    }

    public void markThreadRead(int thread_id){
        /*This wont work in android KitKat and superior:
               https://android-developers.googleblog.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html
           There's no point in setting this the default sms app, so we will need a workaround in php app
         */
        String[] args = new String[]{String.valueOf(thread_id)};
        ContentValues values = new ContentValues();
        values.put("read",true);
        mContext.getContentResolver().update(Uri.parse("content://sms/inbox"), values, "thread_id=?", args);
    }

    public HashMap<String, String> lastSentSmsStatus(){
        HashMap<String,String> ret = new HashMap<String,String>();
        switch (lastSentSMSStatus) {
            case Activity.RESULT_OK:
                ret.put("STATUS","SENT");
                break;
            case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                ret.put("STATUS","ERROR");
                ret.put("DESCRIPTION","GENERIC");
                break;
            case SmsManager.RESULT_ERROR_NO_SERVICE:
                ret.put("STATUS","ERROR");
                ret.put("DESCRIPTION","NO SERVICE");
                break;
            case SmsManager.RESULT_ERROR_NULL_PDU:
                ret.put("STATUS","ERROR");
                ret.put("DESCRIPTION","NULL PDU");
                break;
            case SmsManager.RESULT_ERROR_RADIO_OFF:
                ret.put("STATUS","ERROR");
                ret.put("DESCRIPTION","RADIO OFF");
                break;
            default:
                ret.put("STATUS","UNKNOWN");
                break;
        }
        return ret;
    }

    public void sendSMS(String address, String content) {
        lastSentSMSStatus = -1;
        SmsManager smsManager = SmsManager.getDefault();

        PendingIntent sentPI = PendingIntent.getBroadcast(mContext, 0,
                new Intent("SMS_SENT"), 0);

        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                lastSentSMSStatus = getResultCode();
                Toast.makeText(mContext,"message sent", Toast.LENGTH_LONG).show();
            }
        }, new IntentFilter("SMS_SENT"));

        smsManager.sendTextMessage("tel:".concat(address), null, content, sentPI, null);
    }

    /*This won't actually send the sms, this only opens the default sms app*/
    public void sendSMSIntent(String address, String content){
        Intent smsIntent = new Intent(Intent.ACTION_VIEW);
        smsIntent.setData(Uri.parse("sms:"));
        smsIntent.putExtra("address", address);
        smsIntent.putExtra("sms_body", content);

        mContext.startActivity(smsIntent);
    }
}