package com.kdanmobile.kdan_others_library_for_android.dash2fullscreen;

import android.content.Context;
import android.content.SharedPreferences;

/**
 * Created by Wei on 2017/6/2.
 */

public class Dash2FullScreenAdController {
    private static final long DEFAULT_FIRST_SHOW_IN_TARGET_INTERVAL = 2 * 24 * 60 * 60 * 1000;
    private static final long DEFAULT_ROUTINE_SHOW_IN_TARGET_INTERVAL = 2 * 24 * 60 * 60 * 1000;
    private static final int DEFAULT_MAX_TIMES_LEAVE_WITHOUT_CLICK_IN_TARGET = 3;
    private static final String SP_NAME = "baseDash2AdController";
    private static final String SP_EVER_SHOWN_IN_TARGET = "everShownInTarget";
    private static final String SP_EVER_SHOWN_IN_UPGRADE = "everShownInUpgrade";
    private static final String SP_FIRST_ENTER_TARGET = "firstEnterTarget";
    private static final String SP_LAST_SHOW_IN_TARGET = "lastEnterTarget";
    private static final String SP_LEAVE_DIRECTLY_COUNT = "cancelWithoutClickCount";
    private Context context;
    private Config config;

    public Dash2FullScreenAdController(Context context) {
        this.context = context;
        this.config = new Config();
    }

    public Dash2FullScreenAdController(Context context, Config config) {
        this.context = context;
        this.config = config;
    }

    public void setConfig(Config config) {
        this.config = config;
    }

    void increaseLeaveDirectlyCount() {
        int c = getLeaveDirectlyCount();
        c++;
        getSP().edit()
                .putInt(SP_LEAVE_DIRECTLY_COUNT, c)
                .commit();
    }

    /**
     * Call this method when click upgrade or remove ad btn
     * @param launcher Runnable launcher = () -> {context.startActivity(new Intent(context, Dash2Activity.class))};
     */
    public boolean tryToShowInUpgrade(Runnable launcher) {
        if (hasEverShownInUpgrade()) return false;
        saveEverShownInUpgrade();
        launch(launcher);
        return true;
    }

    /**
     * Call this method when enter target screen
     * <pre>
     * PDF : Reading screen
     * AD : Draw screen
     * NL : Draw screen
     * </pre>
     * @param launcher Runnable launcher = () -> {context.startActivity(new Intent(context, Dash2Activity.class))};
     */
    public boolean tryToShowInTargetScreen(Runnable launcher) {
        return tryToShowInTargetScreen(launcher, System.currentTimeMillis());
    }

    private boolean tryToShowInTargetScreen(Runnable launcher, long current) {
        if (isFirstTimeEnterTargetScreen()) {
            saveFirstEnterTargetScreenTimestamp(current);
            return false;
        }

        if (!hasEverShownInTargetScreen()) {
            long firstTmeEnterTarget = getFirstEnterTargetScreenTimestamp();
            if (current - firstTmeEnterTarget < config.firstShowInTargetScreenInterval) return false;
            launchInTargetScreen(launcher, current);
            return true;
        }

        if (getLeaveDirectlyCount() >= config.maxTimesLeaveDirectlyInTargetScreen) return false;

        long lastShow = getLastShowInTargetScreenTimestamp();
        if (current - lastShow >= config.routineShowInTargetScreenInterval) {
            launchInTargetScreen(launcher, current);
            return true;
        }
        return false;
    }

    private void launchInTargetScreen(Runnable launcher, long current) {
        saveLastShowInTargetScreenTimestamp(current);
        launch(launcher);
    }

    private void launch(Runnable launcher) {
        if (launcher != null) launcher.run();
    }

    private void saveEverShownInTargetScreen() {
        getSP().edit()
                .putBoolean(SP_EVER_SHOWN_IN_TARGET, true)
                .commit();
    }

    private boolean hasEverShownInTargetScreen() {
        return getSP().getBoolean(SP_EVER_SHOWN_IN_TARGET, false);
    }

    private void saveFirstEnterTargetScreenTimestamp(long current) {
        getSP().edit()
                .putLong(SP_FIRST_ENTER_TARGET, current)
                .commit();
    }

    private boolean isFirstTimeEnterTargetScreen() {
        return getFirstEnterTargetScreenTimestamp() == 0;
    }

    private long getFirstEnterTargetScreenTimestamp() {
        return getSP().getLong(SP_FIRST_ENTER_TARGET, 0);
    }

    private void saveLastShowInTargetScreenTimestamp(long current) {
        saveEverShownInTargetScreen();
        getSP().edit()
                .putLong(SP_LAST_SHOW_IN_TARGET, current)
                .commit();
    }

    private long getLastShowInTargetScreenTimestamp() {
        return getSP().getLong(SP_LAST_SHOW_IN_TARGET, 0);
    }

    private int getLeaveDirectlyCount() {
        return getSP().getInt(SP_LEAVE_DIRECTLY_COUNT, 0);
    }

    private void saveEverShownInUpgrade() {
        getSP().edit()
                .putBoolean(SP_EVER_SHOWN_IN_UPGRADE, true)
                .apply();
    }

    private boolean hasEverShownInUpgrade() {
        return getSP().getBoolean(SP_EVER_SHOWN_IN_UPGRADE, false);
    }

    private SharedPreferences getSP() {
        return context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
    }

    public static class Config {
        /**
         * Mills second
         */
        public long firstShowInTargetScreenInterval = DEFAULT_FIRST_SHOW_IN_TARGET_INTERVAL;
        /**
         * Mills second
         */
        public long routineShowInTargetScreenInterval = DEFAULT_ROUTINE_SHOW_IN_TARGET_INTERVAL;
        /**
         * The dash2 ad will not show if user leave directly count more than this value.
         */
        public int maxTimesLeaveDirectlyInTargetScreen = DEFAULT_MAX_TIMES_LEAVE_WITHOUT_CLICK_IN_TARGET;
    }
}
