package com.codegy.aerlink.services.aerlink.cameraremote;

import android.app.Notification;
import android.app.PendingIntent;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.util.Log;
import com.codegy.aerlink.R;
import com.codegy.aerlink.services.aerlink.ALSConstants;
import com.codegy.aerlink.connection.command.Command;
import com.codegy.aerlink.utils.PacketProcessor;
import com.codegy.aerlink.utils.ServiceHandler;
import com.codegy.aerlink.utils.ServiceUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Created by Guiye on 21/5/15.
 */
public class CameraRemoteServiceHandler extends ServiceHandler {

    public interface CameraRemoteCallback {
        void onCameraChangedOpen(boolean open);
        void onCountdownStarted(int countdown);
        void onImageTransferStarted();
        void onImageTransferFinished(Bitmap cameraImage);
    }

    private static final String LOG_TAG = CameraRemoteServiceHandler.class.getSimpleName();

    private static final int NOTIFICATION_CAMERA = 2001;


    private Context mContext;
    private ServiceUtils mServiceUtils;
    private CameraRemoteCallback cameraRemoteCallback;

    private boolean cameraOpen = false;
    private PacketProcessor mPacketProcessor;


    public CameraRemoteServiceHandler(Context context, ServiceUtils serviceUtils) {
        this.mContext = context;
        this.mServiceUtils = serviceUtils;
    }


    public void requestState(Runnable failure) {
        Command cameraCommand = new Command(ALSConstants.SERVICE_UUID, ALSConstants.CHARACTERISTIC_CAMERA_REMOTE_ACTION, new byte[] {
                (byte) 0x02,
        });
        cameraCommand.setFailureBlock(failure);

        mServiceUtils.addCommandToQueue(cameraCommand);
    }

    public void takePicture(Runnable failure) {
        Command cameraCommand = new Command(ALSConstants.SERVICE_UUID, ALSConstants.CHARACTERISTIC_CAMERA_REMOTE_ACTION, new byte[] {
                (byte) 0x03,
        });
        cameraCommand.setImportance(Command.IMPORTANCE_MIN);
        cameraCommand.setFailureBlock(failure);

        mServiceUtils.addCommandToQueue(cameraCommand);
    }

    public void setCameraCallback(CameraRemoteCallback cameraRemoteCallback) {
        this.cameraRemoteCallback = cameraRemoteCallback;
    }

    public void setCameraOpen(boolean cameraOpen) {
        this.cameraOpen = cameraOpen;

        Log.v(LOG_TAG, "Camera " + (cameraOpen ? "OPEN" : "CLOSED"));

        if (cameraRemoteCallback != null) {
            cameraRemoteCallback.onCameraChangedOpen(cameraOpen);
        }

        if (cameraOpen) {
            Bitmap background = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.bg_camera);

            Intent cameraIntent = new Intent(mContext, CameraRemoteActivity.class);
            cameraIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            PendingIntent cameraPendingIntent = PendingIntent.getActivity(mContext, 0, cameraIntent, 0);

            Icon cameraIcon = Icon.createWithResource(mContext, R.drawable.nic_camera);
            Notification.Action cameraAction = new Notification.Action.Builder(
                    cameraIcon,
                    "Camera",
                    cameraPendingIntent
            ).build();

            Notification.WearableExtender wearableExtender = new Notification.WearableExtender()
                    .setBackground(background)
                    .setContentIcon(R.drawable.nic_camera)
                    .setHintHideIcon(true)
                    .setContentAction(0)
                    .addAction(cameraAction);

            Notification.Builder builder = new Notification.Builder(mContext)
                    .setSmallIcon(cameraIcon)
                    .setContentTitle(mContext.getString(R.string.take_photo_title))
                    .setContentText(mContext.getString(R.string.take_photo_text))
                    .setPriority(Notification.PRIORITY_MAX)
                    .extend(wearableExtender);

            mServiceUtils.notify(null, NOTIFICATION_CAMERA, builder.build());
        }
        else {
            mServiceUtils.cancelNotification(null, NOTIFICATION_CAMERA);
        }
    }

    public boolean isCameraOpen() {
        return cameraOpen;
    }


    @Override
    public void reset() {
        cameraOpen = false;
        mPacketProcessor = null;
    }

    @Override
    public UUID getServiceUUID() {
        return ALSConstants.SERVICE_UUID;
    }

    @Override
    public List<String> getCharacteristicsToSubscribe() {
        List<String> characteristics = new ArrayList<>();

        characteristics.add(ALSConstants.CHARACTERISTIC_CAMERA_REMOTE_DATA);

        return characteristics;
    }

    @Override
    public boolean canHandleCharacteristic(BluetoothGattCharacteristic characteristic) {
        String characteristicUUID = characteristic.getUuid().toString().toLowerCase();
        return characteristicUUID.equals(ALSConstants.CHARACTERISTIC_CAMERA_REMOTE_DATA);
    }

    @Override
    public void handleCharacteristic(BluetoothGattCharacteristic characteristic) {
        byte[] packet = characteristic.getValue();

        if (mPacketProcessor == null) {
            mPacketProcessor = new PacketProcessor(packet);

            switch (mPacketProcessor.getAction()) {
                case 0x01:
                    if (mPacketProcessor.getStatus() != 0x01) {
                        mPacketProcessor = null;
                    }
                    else if (cameraRemoteCallback != null) {
                        cameraRemoteCallback.onImageTransferStarted();
                    }
                    break;
                case 0x02:
                    setCameraOpen(mPacketProcessor.getStatus() == 0x01);
                    mPacketProcessor = null;
                    return;
                case 0x03:
                    if (cameraRemoteCallback != null) {
                        cameraRemoteCallback.onCountdownStarted(mPacketProcessor.getStatus());
                    }
                    mPacketProcessor = null;
                    return;
            }
        }
        else {
            mPacketProcessor.process(packet);
        }

        if (mPacketProcessor != null && mPacketProcessor.isFinished()) {
            Bitmap cameraImage = mPacketProcessor.getBitmapValue();

            if (cameraImage != null && cameraRemoteCallback != null) {
                cameraRemoteCallback.onImageTransferFinished(cameraImage);
            }

            mPacketProcessor = null;
        }
    }


}