package cgmblelib.database.repository;

import android.content.Context;

import androidx.lifecycle.LiveData;

import java.util.Date;
import java.util.List;

import cgmblelib.Enum.enumUnBind;
import cgmblelib.database.AppDatabase;
import cgmblelib.database.dao.DaoDevice;
import cgmblelib.database.entity.PocDevice;
import cgmblelib.database.source.SourceDevice;
import cgmblelib.database.source.db.DeviceDBDataSource;
import cgmblelib.utils.AppExecutors;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by minyuchun on 2019/1/11.
 * repository
 *
 * @author minyuchun
 */

public class RepositoryDevice implements SourceDevice {
    /**
     * 单例
     */
    private static RepositoryDevice INSTANCE;
    /***
     * 本地数据连接
     */
    private final DeviceDBDataSource mDeviceDBDataSource;

    public RepositoryDevice(Context context) {
        DaoDevice mDaoDevice = AppDatabase.getInMemoryDatabase(context).mDaoDevice();
        mDeviceDBDataSource = DeviceDBDataSource.getInstance(new AppExecutors(), mDaoDevice);
    }

    public static RepositoryDevice getInstance(Context context) {
        if (INSTANCE == null) {
            synchronized (RepositoryDevice.class) {
                if (INSTANCE == null) {
                    INSTANCE = new RepositoryDevice(context);
                }
            }
        }
        return INSTANCE;
    }

    /**
     * 连接/断开连接 发射器
     *
     * @param pocDevice 需要操作的发射器
     * @param isConnect 连接/断开连接
     * @return 操作是否成功
     */
    public boolean connectIoThread(PocDevice pocDevice, boolean isConnect) {
        try {
            if (isConnect) {
                pocDevice.setConnectDate(new Date());
                pocDevice.setDisConnectDate(null);
            } else {
                pocDevice.setDisConnectDate(new Date());
            }
            return updateDeviceIoThread(pocDevice) > 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 修改设备连接状态
     *
     * @param pocDevice      设备信息
     * @param disConnectDate 断开连接的时间
     * @return 是否修改成功
     */
    public boolean disconnectIoThread(PocDevice pocDevice, Date disConnectDate) {
        try {
            pocDevice.setDisConnectDate(disConnectDate);
            return updateDeviceIoThread(pocDevice) > 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 在主线程解除绑定发射器
     *
     * @param unBindType 解除绑定的类型
     * @param observer   监听
     */
    public void unBindMainThread(enumUnBind unBindType, Observer<PocDevice> observer) {
        Observable.just(unBindType)
                .subscribeOn(Schedulers.io())
                .map(unBind -> {
                    PocDevice device = getLatestDeviceIoThread();
                    if (device != null) {
                        if (unBindIoThread(device, unBind)) {
                            return getDeviceByIdIoThread(device.getId());
                        }
                    }
                    return device;
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 在子线程解除绑定
     *
     * @param pocDevice 需要操作的发射器
     * @param unBind    解除绑定的类型
     * @return 是否家畜绑定成功
     */
    public boolean unBindIoThread(PocDevice pocDevice, enumUnBind unBind) {
        try {
            Date date = new Date();
            pocDevice.setDisConnectDate(date);
            if (pocDevice.getInitEndDate() == null) {
                pocDevice.setInitEndDate(date);
            }
            pocDevice.setUnBindDate(date);
            if (pocDevice.getUnBind() != enumUnBind.UNBIND_COMMAND) {
                pocDevice.setUnBind(unBind);
            }
            return updateDeviceIoThread(pocDevice) > 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public long insertDeviceIoThread(PocDevice device) {
        return mDeviceDBDataSource.insertDeviceIoThread(device);
    }

    @Override
    public long insertDeviceIoThread(String address, String name) {
        return mDeviceDBDataSource.insertDeviceIoThread(address, name);
    }

    @Override
    public void deleteDevice(PocDevice device) {
        mDeviceDBDataSource.deleteDevice(device);
    }

    @Override
    public void deleteAllDevices() {
        mDeviceDBDataSource.deleteAllDevices();
    }

    @Override
    public void deleteAllDeviceData() {
        mDeviceDBDataSource.deleteAllDeviceData();
    }

    @Override
    public void updateDevice(PocDevice device) {
        mDeviceDBDataSource.updateDevice(device);
    }

    @Override
    public int updateDeviceIoThread(PocDevice device) {
        return mDeviceDBDataSource.updateDeviceIoThread(device);
    }

    @Override
    public PocDevice getLatestDeviceIoThread() {
        return mDeviceDBDataSource.getLatestDeviceIoThread();
    }

    @Override
    public PocDevice getLatestDeviceIoThread(String address) {
        return mDeviceDBDataSource.getLatestDeviceIoThread(address);
    }

    @Override
    public LiveData<PocDevice> getLiveDataLatestDeviceIoThread() {
        return mDeviceDBDataSource.getLiveDataLatestDeviceIoThread();
    }

    @Override
    public PocDevice getDeviceByIdIoThread(int deviceId) {
        return mDeviceDBDataSource.getDeviceByIdIoThread(deviceId);
    }

    @Override
    public List<PocDevice> getDeviceListGroupByAddressIoThread() {
        return mDeviceDBDataSource.getDeviceListGroupByAddressIoThread();
    }

    @Override
    public List<PocDevice> getDeviceListByAddressIoThread(String address) {
        return mDeviceDBDataSource.getDeviceListByAddressIoThread(address);
    }

    @Override
    public void getLatestFlowableDevice(Consumer<PocDevice> consumer) {
        mDeviceDBDataSource.getLatestFlowableDevice(consumer);
    }
}
