package com.mogo.cloud.location.third.service;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.elegant.utils.ThreadPoolService;
import com.mogo.cloud.location.LocationConfig;
import com.mogo.cloud.location.third.core.LocUploadConfig;
import com.mogo.cloud.location.third.core.Location;
import com.mogo.cloud.location.third.core.LocationDelegateManager;
import com.mogo.cloud.location.third.core.LocationServiceProvider;
import com.zhidao.ptech.connsvr.payload.protocol.MogoPayload;
import com.zhidao.socket.Callback;
import com.zhidao.socket.CallbackManager;
import com.zhidao.socket.SocketClient;

import java.util.LinkedList;

public class UploadDataService extends Service {

    private static final String TAG = "UploadDataService";

    private static final int MAX_LOCATION_CACHE_SIZE = 5;

    private final LinkedList<MogoPayload.Coordinate> coordinates = new LinkedList<>();

    private Handler handler;

    private final Callback callback = new Callback() {
        @Override
        public void update(@NonNull CallbackManager manager, @NonNull byte[] message, String appId, long msgId) {
        }

        @Override
        public void onAck(@NonNull CallbackManager manager, @NonNull byte[] headerBytes, byte[] content) {
        }
    };

    private final Runnable uploadTask = new Runnable() {
        @Override
        public void run() {
            ThreadPoolService.execute(UploadDataService.this::publishData);
            handler.postDelayed(uploadTask, 5 * LocUploadConfig.instance().getLocInterval());
        }
    };

    private final Runnable buildLocationTask = new Runnable() {
        @Override
        public void run() {
            final LocationServiceProvider provider = LocationDelegateManager.getInstance().getLocationServiceProvider();
            if (provider != null) {
                final Location location = new Location();
                location.setAccuracy(provider.getAccuracy());
                location.setAdCode(provider.getAdCode());
                location.setAltitude(provider.getAltitude());
                location.setBearing(provider.getBearing());
                location.setCarStatus(provider.getCarStatus());
                location.setCityCode(provider.getCityCode());
                location.setCityName(provider.getCityName());
                location.setGpsAccuracyStatus(provider.getGpsAccuracyStatus());
                location.setLatitude(provider.getLatitude());
                location.setLongitude(provider.getLongitude());
                location.setLocType(provider.getLocType());
                location.setProvider(provider.getProvider());
                location.setSatellites(provider.getSatellites());
                location.setSpeed(provider.getSpeed());
                location.setTime(provider.getTime());
                buildCoordinates(location);
            }
            handler.postDelayed(this, LocUploadConfig.instance().getLocInterval());
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SocketClient.getInstance().registerSocketCallback(callback);
        HandlerThread mHandlerThread = new HandlerThread("upload_data_thread");
        mHandlerThread.start();
        handler = new Handler(mHandlerThread.getLooper());
        handler.post(buildLocationTask);
        handler.postDelayed(uploadTask, 5 * LocUploadConfig.instance().getLocInterval());
    }

    private void publishData() {
        synchronized (coordinates) {
            final MogoPayload.MogoCoornateReq coordinateReq = SocketRequestUtil.getCoordinateReq(coordinates);
            if (coordinateReq != null) {
                SocketRequestUtil.sendCoordinateReqBySocket(coordinateReq, true, System.currentTimeMillis());
            }
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return Service.START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        SocketClient.getInstance().unregisterSocketCallback(callback);
        handler.removeCallbacks(uploadTask);
        handler.removeCallbacks(buildLocationTask);
        clearLocationCache();
    }

    private void buildCoordinates(Location location) {
        MogoPayload.Coordinate coordinate = SocketRequestUtil.buildBCoordinate(location);
        if (coordinate.getLat() != 0 && coordinate.getLon() != 0) {
//            if (LocationConfig.isPrintLog) {
//                Log.d(TAG, "socket-location is " + location.toString());
//                Log.d(TAG, "socket-coordinates.size()" + coordinates.size());
//            }
            synchronized (coordinates) {
                coordinates.offer(coordinate);
            }
        } else {
            if (LocationConfig.isPrintLog) {
                Log.d(TAG, "coordinates size is 0, give up uploading for Socket");
            }
        }
        synchronized (coordinates) {
            while (coordinates.size() > MAX_LOCATION_CACHE_SIZE) {
                coordinates.pop();
            }
        }
    }

    private void clearLocationCache() {
        synchronized (coordinates) {
            coordinates.clear();
        }
    }
}
