package com.renrenliao.im.utils.ntp;

import static com.renrenliao.im.utils.ntp.TrueTime._ntpHost;

import android.content.Context;
import android.os.Handler;
import android.util.Log;


import com.renrenliao.im.utils.NetworkUtils;

import java.util.Date;
import java.util.concurrent.atomic.AtomicBoolean;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;

/**
 * @author pony
 * @name android_chatnow
 * @time 2020-04-10 14:00
 * @class describe
 */
public class NtpSync {
    private static final String TAG = NtpSync.class.getSimpleName();
    //    public static final ExecutorService ntpThread = new ThreadPoolExecutor(1, 2,
//            0L, TimeUnit.MILLISECONDS,
//            new LinkedBlockingQueue<Runnable>(Integer.MAX_VALUE));
    public static long AUTO_RE_SYNC_TIME = 1500;
    private AtomicBoolean autoSyncTime = new AtomicBoolean(false);
    private Context context;
    private Handler handler;
    private Runnable runnable;

    private static class LazyHolder {
        static final NtpSync INSTANCE = new NtpSync();
    }

    public static NtpSync getInstance() {
        return LazyHolder.INSTANCE;
    }

    public NtpSync() {
        handler = new Handler();
        runnable = new Runnable() {
            @Override
            public void run() {
                if (NetworkUtils.isNetWorkAvailable(context)) {
                    autoSyncTime.compareAndSet(false, true);
                    DisposableSingleObserver<Date> disposable = TrueTimeRx.build()
                            .withConnectionTimeout(20_428)
                            .withRetryCount(100)
                            .withSharedPreferencesCache(context)
                            .withLoggingEnabled(true)
                            .initializeRx1(_ntpHost)
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribeWith(new DisposableSingleObserver<Date>() {
                                @Override
                                public void onSuccess(Date date) {
                                    Log.e(TAG, "Success initialized TrueTime :" + date.toString());
                                    autoSyncTime.compareAndSet(true, false);
                                    if (!autoSyncTime.get()) {
                                        stop();
                                        handler.postDelayed(runnable, 30 * 60 * 1000);
                                    }
                                }

                                @Override
                                public void onError(Throwable e) {
                                    Log.e(TAG, "something went wrong when trying to initializeRx TrueTime", e);
                                    autoSyncTime.compareAndSet(true, false);
                                    start(false);

                                }
                            });
                } else {
                    Log.e(TAG, "no network");
                    start(false);
                }
            }
        };
    }


    public boolean hasRefershing() {
        return autoSyncTime.get();
    }

    public void initNtp(Context context) {
        this.context = context;
        TrueTimeRx.build()
                .withConnectionTimeout(20_428)
                .withRetryCount(100)
                .withSharedPreferencesCache(context)
                .withLoggingEnabled(true)
                .initializeRx1(_ntpHost);
    }

    public void stop() {
        this.handler.removeCallbacksAndMessages(null);
    }

    public void start(boolean immediately) {
        if (!autoSyncTime.get()) {
            this.stop();
            this.handler.postDelayed(this.runnable, immediately ? 0L : AUTO_RE_SYNC_TIME);
        }
    }

    public boolean isAutoReLoginRunning() {
        return this.autoSyncTime.get();
    }


}
