package com.app.simplitend.welcome.welcomepatient.fragments.contacts.mvvm;

import android.app.Application;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.bumptech.glide.Glide;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.app.simplitend.R;
import com.app.simplitend.databinding.DecisionBottomsheetBinding;
import com.app.simplitend.databinding.DoneBottomsheetBinding;
import com.app.simplitend.welcome.welcomepatient.mvvm.WelcomeContracts;

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

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import okhttp3.MultipartBody;
import okhttp3.RequestBody;

public class ContactViewModel extends AndroidViewModel {

    private static final String TAG = "ContactViewModel";

    private final UserContactRepository contactRepository;

    private GotoAddContactInterface gotoAddContactInterface;

    private SOSCheckInterface sosCheckInterface;

    private final MutableLiveData<ArrayList<ArrayList<Contact>>> mutableContactList;
    private final LiveData<ArrayList<ArrayList<Contact>>> live_contact_list;

    public ContactViewModel(Application application){
        super(application);
        this.contactRepository = UserContactRepository.getContactRepository();
        mutableContactList = new MutableLiveData<>(null);
        live_contact_list = mutableContactList;
    }

    public LiveData<ArrayList<ArrayList<Contact>>> getLive_contact_list() {
        return live_contact_list;
    }

    public ArrayList<ArrayList<Contact>> getContactList(Context context) {
        ArrayList<ArrayList<Contact>> contactLIst = new ArrayList<>();

        HashMap<String, Set<Contact>> contactMap = this.contactRepository.getContactList(context);

        for (Set<Contact> contacts: contactMap.values()){
            if (contacts != null && contacts.size() > 0){
                contactLIst.add(new ArrayList<>(contacts));
            }
        }

        Collections.sort(contactLIst, (contacts, t1) -> contacts.get(0).first_name.toLowerCase().compareTo(t1.get(0).first_name.toLowerCase()));

        return contactLIst;
    }

    public Uri accessPHotoUri(Context context, String photo_uri) {
        // Create a ContentResolver
        ContentResolver contentResolver = context.getContentResolver();

        try {
            // Convert the PHOTO_URI string to a Uri object
            Uri uri = Uri.parse(photo_uri);

            // Use ContentResolver to open an InputStream from the Uri
            InputStream inputStream = contentResolver.openInputStream(uri);

            if (inputStream != null) {
                // Decode the InputStream into a Bitmap
                Bitmap contactPhoto = BitmapFactory.decodeStream(inputStream);

                File file = new File(context.getCacheDir(), "img_temp_contact");
                // Create an output stream to write the Bitmap data to the file
                FileOutputStream outputStream = new FileOutputStream(file);

                // Compress and save the Bitmap as a PNG file (you can choose a different format)
                contactPhoto.compress(Bitmap.CompressFormat.PNG, 40, outputStream);

                // Close the output stream and input stream when done
                outputStream.close();

                // Close the InputStream when done
                inputStream.close();

                return Uri.fromFile(file);
            }
        } catch (Exception e) {
            // do nothing
        }

        return null;
    }

    public UserContactRepository getContactRepository() {
        return contactRepository;
    }

    public void setGotoAddContactInterface(GotoAddContactInterface gotoAddContactInterface) {
        this.gotoAddContactInterface = gotoAddContactInterface;
    }

    public void setSosCheckInterface(SOSCheckInterface sosCheckInterface) {
        this.sosCheckInterface = sosCheckInterface;
    }

    public void getRemoteContactList(WelcomeContracts.ContactListContracts contactListContracts, String token){
        contactRepository.getRemoteContactList(contactListContracts, token);
    }

    public void createEditContact(@NonNull String URL,
                                  Map<String, RequestBody> body,
                                  Map<String, Integer> intBody,
                                  MultipartBody.Part userImage,
                                  WelcomeContracts.CreateContactInterface createContactInterface,
                                  WelcomeContracts.UpdateContactContracts updateContactContracts,
                                  @NonNull String token){
        contactRepository.createEditContact(URL, body, intBody, userImage, createContactInterface, updateContactContracts, token);
    }

    public void deleteContact(String token, int contact_id, WelcomeContracts.DeleteContactInterface deleteContactInterface){
        contactRepository.deleteContact(contact_id, "Bearer " + token,
                deleteContactInterface);
    }

    public void showDoneBottomSheet(Context context) {
        DoneBottomsheetBinding binding = DoneBottomsheetBinding.inflate(LayoutInflater.from(context));

        BottomSheetDialog bsd = new BottomSheetDialog(context, R.style.BottomSheetDialog);
        bsd.setContentView(binding.getRoot());
        bsd.setCancelable(false);

        binding.text.setText(context.getString(R.string.changes_successful));

        Glide.with(context)
                .asGif()
                .load(R.raw.done_anim_primary)
                .into(binding.doneAnim);

        bsd.show();

        gotoAddContactFragment(3000, bsd);
    }

    private void gotoAddContactFragment(long inMsm, BottomSheetDialog bsd){
        if (gotoAddContactInterface != null) gotoAddContactInterface.gotoAddFragment(bsd);
    }

    public void showSOSDecision(Context context, boolean isSosSet, String sos_contact_name, String current_name) {

        DecisionBottomsheetBinding binding = DecisionBottomsheetBinding.inflate(LayoutInflater.from(context));

        BottomSheetDialog bsd = new BottomSheetDialog(context, R.style.BottomSheetDialog);
        bsd.setContentView(binding.getRoot());
        bsd.setCancelable(false);

        String title;

        if (isSosSet && sos_contact_name != null){
            title = "You are about to change emergency number from " + sos_contact_name + " to this contact. Please confirm";
        }else{
            title = context.getString(R.string.make_sos);
        }

        binding.text.setText(title);

        binding.positiveBtn.setText(context.getString(R.string.yes));
        binding.negativeBtn.setText(context.getString(R.string.no));

        binding.negativeBtn.setOnClickListener(v -> {
            bsd.dismiss();
            if (sosCheckInterface != null) sosCheckInterface.onCheckChange(false);
        });

        binding.positiveBtn.setOnClickListener(v -> {
            bsd.dismiss();
            if (sosCheckInterface != null) sosCheckInterface.onCheckChange(true);
        });

        bsd.show();

    }

    public ArrayList<String> loadCountryCodeDropDown(Context context) {

        ArrayList<String> countryCodeList = new ArrayList<>();

        try {

            String countryCodeStr = readCountryCodes(context);
            JSONArray jsonArray = new JSONArray(countryCodeStr);

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

                JSONObject code = jsonArray.getJSONObject(i);

                countryCodeList.add(code.getString("dial_code"));

            }

        } catch (Exception e) {

            // if cannot load all country codes showing only india's dial code
            countryCodeList.add("+91");

            Log.e(TAG, "loadCountryCodeDropDown: ", e);
        }

        return countryCodeList;
    }

    public String readCountryCodes(Context context) throws IOException {
        StringBuilder returnString = new StringBuilder();

        InputStream fIn = context.getResources().openRawResource(R.raw.country_code);
        InputStreamReader isr = new InputStreamReader(fIn);
        BufferedReader input = new BufferedReader(isr);

        String line = "";

        while ((line = input.readLine()) != null) {
            returnString.append(line);
        }

        try {
            isr.close();

            if (fIn != null) fIn.close();

            input.close();

        } catch (Exception e) {
            Log.e(TAG, "readCountryCodes: ", e);
        }

        return returnString.toString();
    }


    // interfaces
    public interface GotoAddContactInterface{
        void gotoAddFragment(BottomSheetDialog bsd);
    }

    public interface SOSCheckInterface{
        void onCheckChange(boolean state);
    }

}
