package in.slanglabs;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.drawable.DrawableCompat;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URL;

import in.slanglabs.assistants.retail.SlangConvaTrigger;

public class RNSlangConvaTriggerViewManager extends SimpleViewManager<SlangConvaTrigger> {

    public static final String REACT_CLASS = "RNSlangConvaTrigger";
    public static String TAG = "RNSlangConvaTriggerViewManager";

    ReactApplicationContext mCallerContext;

    @NonNull
    @Override
    public String getName() {
        return REACT_CLASS;
    }

    public RNSlangConvaTriggerViewManager(ReactApplicationContext context) {
        mCallerContext = context;
    }

    @NonNull
    @Override
    protected SlangConvaTrigger createViewInstance(@NonNull ThemedReactContext reactContext) {
        SlangConvaTrigger convaTrigger = new SlangConvaTrigger(reactContext);
        convaTrigger.setImageDrawable(ContextCompat.getDrawable(reactContext, R.drawable.trigger));
        LifecycleEventListener listener = new LifecycleEventListener() {
            @Override
            public void onHostResume() {
            }

            @Override
            public void onHostPause() {
            }

            @Override
            public void onHostDestroy() {
                convaTrigger.onDetachedFromWindow();
            }
        };

        mCallerContext.addLifecycleEventListener(listener);
        return convaTrigger;
    }

    @ReactProp(name = "src")
    public void setSrc(SlangConvaTrigger view, @Nullable ReadableMap map) {
        String uriString = map.getString("uri");
        Log.d(TAG, "setTriggerImageResource: " + uriString);
        try {
            // Debug
            if (uriString.startsWith("http")) {
                new SampleAsync(view, urlString -> {
                    try {
                        URL url = new URL(urlString);
                        return BitmapFactory.decodeStream(url.openConnection().getInputStream());
                    } catch (IOException e) {
                        sendAssistantError(e);
                    }
                    return null;
                }, uriString).execute();
            } else {
                // Release
                new SampleAsync(view, urlString -> {
                    try {
                        int resourceId = mCallerContext.getResources().getIdentifier(
                                uriString, "drawable", mCallerContext.getPackageName()
                        );
                        return BitmapFactory.decodeResource(
                                mCallerContext.getResources(),
                                resourceId
                        );
                    } catch (Exception e) {
                        sendAssistantError(e);
                    }
                    return null;
                }, uriString).execute();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendAssistantError(Exception exception) {
        WritableMap params = Arguments.createMap();
        params.putString("type", exception.getMessage());
        sendEvent("onAssistantError", params);
    }

    private void sendEvent(String name, WritableMap params) {
        mCallerContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(name, params);
    }

    private interface BitmapDownloadInterface {
        Bitmap downloadBitmapImage(String urlString);
    }

    private static class SampleAsync extends AsyncTask<Void, Void, Bitmap> {

        private WeakReference<ImageView> mImageView;
        private BitmapDownloadInterface mBitmapDownloadInterface;
        private String mUrlString;

        SampleAsync(ImageView imageView, BitmapDownloadInterface bitmapDownloadInterface, String urlString) {
            mImageView = new WeakReference<>(imageView);
            mBitmapDownloadInterface = bitmapDownloadInterface;
            mUrlString = urlString;
        }

        @Override
        protected Bitmap doInBackground(Void... params) {
            try {
                return mBitmapDownloadInterface.downloadBitmapImage(mUrlString);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap bmp) {
            super.onPostExecute(bmp);
            if (bmp != null) {
                if (mImageView != null && mImageView.get() != null) {
                    mImageView.get().setImageBitmap(bmp);
                }
            }
        }
    }

}
