/* 
 * Copyright 2015 by AVM GmbH <info@avm.de>
 *
 * This software contains free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License ("License") as 
 * published by the Free Software Foundation  (version 3 of the License). 
 * This software is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the copy of the 
 * License you received along with this software for more details.
 */

package de.avm.fundamentals.helper;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Logger;
import com.google.android.gms.analytics.Tracker;
import de.avm.fundamentals.logger.FileLog;

import java.util.Map;

public class GoogleAnalyticsHelper {

    private static final String ANALYTICS_PREFERENCES = "analytics_preferences";
    private static final String TRACKING_OPT_OUT = "tracking_opt_out";

    /**
     * If this variable is set to true - Google Analytics is completely disabled, no dryRun, no Log, no initialisation
     */
    public static final boolean GOOGLE_ANALYTICS_DISABLED = false;

    private static String mTrackingId;
    private static Tracker mAppTracker;
    private static Context mContext;

    public static boolean isGoogleAnalyticsDisabled(){
        return GOOGLE_ANALYTICS_DISABLED;
    }

    /**
     * Methode to instantiate GoogleAnalytics, this should be done in your {@link android.app.Application} class
     * @param context the ApplicationContext of your app
     * @param trackingId the TrackingId from GoogleAnalytics
     * @param debug true tu run Google Analytics in dryRun mode and print Log, false for release version
     */
    public static void initialise(final Context context, final String trackingId, final boolean debug){
        mTrackingId = trackingId;
        mContext = context;
        initTracker();
        setDebugMode(debug);
        setGoogleAnalyticsOptOut(getGoogleAnalyticsOptOut());
    }

    private static void setDebugMode(boolean debug) {
        if(debug){
            GoogleAnalytics analytics = GoogleAnalytics.getInstance(mContext);
            analytics.getLogger().setLogLevel(Logger.LogLevel.VERBOSE);
            analytics.setDryRun(true);
        }
    }

    private static void initTracker() {
        if (mAppTracker == null) {
            GoogleAnalytics analytics = GoogleAnalytics.getInstance(mContext);
            mAppTracker = analytics.newTracker(mTrackingId);
            mAppTracker.setAnonymizeIp(true); //we signed to do this!
            mAppTracker.enableExceptionReporting(true);
            mAppTracker.setSessionTimeout(300);
        }
    }

    /**
     * Sets the Google Analytics opt out option to disable/enable the tracking.
     * @param optOut true enables opt out, false otherwise
     */
    public static void setGoogleAnalyticsOptOut(final boolean optOut){
        checkAnalyticsInitialisation();
        if(isGoogleAnalyticsDisabled()) {
            FileLog.d("Google Analytics disabled.");
            GoogleAnalytics.getInstance(mContext).setAppOptOut(isGoogleAnalyticsDisabled());
        } else {
            if (!GoogleAnalytics.getInstance(mContext).isDryRunEnabled()) {
                FileLog.d("Google Analytics enabled.");
            } else {
                FileLog.d("Google Analytics disabled (dry run).");
            }
            SharedPreferences preferences = mContext.getSharedPreferences(ANALYTICS_PREFERENCES, Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = preferences.edit();
            editor.putBoolean(TRACKING_OPT_OUT, optOut);
            editor.commit();
            GoogleAnalytics.getInstance(mContext).setAppOptOut(optOut);
        }
    }

    /**
     * @return if Google Analytics opt out is enabled or disabled. true means Google Analytics is disabled
     */
    public static boolean getGoogleAnalyticsOptOut(){
        checkAnalyticsInitialisation();
        SharedPreferences preferences = mContext.getSharedPreferences(ANALYTICS_PREFERENCES, Context.MODE_PRIVATE);
        return preferences.getBoolean(TRACKING_OPT_OUT, false);
    }

    private static Tracker getTracker() {
        checkAnalyticsInitialisation();
        return mAppTracker;
    }

    /**
     * Tracks the screen name
     * @param screenName String which represents the name of the screen you want to track
     */
    public static void trackScreen(final String screenName){
        checkAnalyticsInitialisation();
        Tracker tracker = getTracker();
        tracker.setScreenName(screenName);
        send(tracker, new HitBuilders.AppViewBuilder().build());
        FileLog.d("Screen: " + screenName);
    }

    /**
     * Tracks an event with the given category, action and label.
     * @param category Category name
     * @param action Action name
     * @param label Label for the action
     */
    public static void trackEvent(final String category, final String action, final String label){
        checkAnalyticsInitialisation();
        send(getTracker(), new HitBuilders.EventBuilder()
                .setCategory(category)
                .setAction(action)
                .setLabel(label)
                .build());
        FileLog.d("Event: " + category + " | " + action + " | " + label);
    }

    /**
     * Tracks an event with the given category, action and label.
     * @param category Category name
     * @param action Action name
     * @param value value for the action
     */
    public static void trackEvent(final String category, final String action, final long value){
        checkAnalyticsInitialisation();
        send(getTracker(), new HitBuilders.EventBuilder()
                .setCategory(category)
                .setAction(action)
                .setValue(value)
                .build());
        FileLog.d("Event: " + category + " | " + action + " | " + value);
    }

    /**
     * Tracks an event with the given category and action. This event will be send without a label
     * @param category Category name
     * @param action Action name
     */
    public static void trackEvent(final String category, final String action){
        checkAnalyticsInitialisation();
        send(getTracker(), new HitBuilders.EventBuilder()
                .setCategory(category)
                .setAction(action)
                .build());
        FileLog.d("Event: " + category + " | " + action );
    }

    private static void send(final Tracker tracker, final Map<String, String> params){
        if(!isGoogleAnalyticsDisabled()) {
            tracker.send(params);
        }
    }

    private static void checkAnalyticsInitialisation() {
        if(TextUtils.isEmpty(mTrackingId) || mContext == null){
            throw new IllegalStateException("Google Analytics was not initialised. Call TrackingHelper.initialise() on App start");
        }
    }

}
