/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko.promotion;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import org.mozilla.gecko.GeckoApplication;
import org.mozilla.gecko.GeckoProfile;
import org.mozilla.gecko.Locales;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.db.UrlAnnotations;
import org.mozilla.gecko.icons.IconCallback;
import org.mozilla.gecko.icons.IconResponse;
import org.mozilla.gecko.icons.Icons;
import org.mozilla.gecko.Experiments;
import org.mozilla.gecko.util.ActivityUtils;
import org.mozilla.gecko.util.ThreadUtils;

/**
 * Prompt to promote adding the current website to the home screen.
 */
public class HomeScreenPrompt extends Locales.LocaleAwareActivity implements IconCallback {
    private static final String EXTRA_TITLE = "title";
    private static final String EXTRA_URL = "url";

    private static final String TELEMETRY_EXTRA = "home_screen_promotion";

    private View containerView;
    private ImageView iconView;
    private String title;
    private String url;
    private boolean isAnimating;
    private boolean hasAccepted;
    private boolean hasDeclined;

    public static void show(Context context, String url, String title) {
        Intent intent = new Intent(context, HomeScreenPrompt.class);
        intent.putExtra(EXTRA_TITLE, title);
        intent.putExtra(EXTRA_URL, url);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        fetchDataFromIntent();
        setupViews();
        loadShortcutIcon();

        slideIn();

        Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, Experiments.PROMOTE_ADD_TO_HOMESCREEN);

        // Technically this isn't triggered by a "service". But it's also triggered by a background task and without
        // actual user interaction.
        Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.SERVICE, TELEMETRY_EXTRA);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, Experiments.PROMOTE_ADD_TO_HOMESCREEN);
    }

    private void fetchDataFromIntent() {
        final Bundle extras = getIntent().getExtras();

        title = extras.getString(EXTRA_TITLE);
        url = extras.getString(EXTRA_URL);
    }

    private void setupViews() {
        setContentView(R.layout.homescreen_prompt);

        ((TextView) findViewById(R.id.title)).setText(title);

        Uri uri = Uri.parse(url);
        ((TextView) findViewById(R.id.host)).setText(uri.getHost());

        containerView = findViewById(R.id.container);
        iconView = (ImageView) findViewById(R.id.icon);

        findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hasAccepted = true;

                addToHomeScreen();
            }
        });

        findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onDecline();
            }
        });
    }

    private void addToHomeScreen() {
        ThreadUtils.postToBackgroundThread(new Runnable() {
            @Override
            public void run() {
                GeckoApplication.createBrowserShortcut(title, url);

                Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, TELEMETRY_EXTRA);

                ActivityUtils.goToHomeScreen(HomeScreenPrompt.this);

                finish();
            }
        });
    }

    private void loadShortcutIcon() {
        Icons.with(this)
                .pageUrl(url)
                .skipNetwork()
                .skipMemory()
                .forLauncherIcon()
                .build()
                .execute(this);
    }

    private void slideIn() {
        containerView.setTranslationY(500);
        containerView.setAlpha(0);

        final Animator translateAnimator = ObjectAnimator.ofFloat(containerView, "translationY", 0);
        translateAnimator.setDuration(400);

        final Animator alphaAnimator = ObjectAnimator.ofFloat(containerView, "alpha", 1);
        alphaAnimator.setStartDelay(200);
        alphaAnimator.setDuration(600);

        final AnimatorSet set = new AnimatorSet();
        set.playTogether(alphaAnimator, translateAnimator);
        set.setStartDelay(400);

        set.start();
    }

    /**
     * Remember that the user rejected creating a home screen shortcut for this URL.
     */
    private void rememberRejection() {
        ThreadUtils.postToBackgroundThread(new Runnable() {
            @Override
            public void run() {
                final UrlAnnotations urlAnnotations = BrowserDB.from(HomeScreenPrompt.this).getUrlAnnotations();
                urlAnnotations.insertHomeScreenShortcut(getContentResolver(), url, false);
            }
        });
    }

    private void slideOut() {
        if (isAnimating) {
            return;
        }

        isAnimating = true;

        ObjectAnimator animator = ObjectAnimator.ofFloat(containerView, "translationY", containerView.getHeight());
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                finish();
            }

        });
        animator.start();
    }

    @Override
    public void finish() {
        super.finish();

        // Don't perform an activity-dismiss animation.
        overridePendingTransition(0, 0);
    }

    @Override
    public void onBackPressed() {
        onDecline();
    }

    private void onDecline() {
        if (hasDeclined || hasAccepted) {
            return;
        }

        rememberRejection();
        slideOut();

        // Technically not always an action triggered by the "back" button but with the same effect: Finishing this
        // activity and going back to the previous one.
        Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL, TelemetryContract.Method.BACK, TELEMETRY_EXTRA);

        hasDeclined = true;
    }

    /**
     * User clicked outside of the prompt.
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        onDecline();

        return true;
    }

    @Override
    public void onIconResponse(IconResponse response) {
        iconView.setImageBitmap(response.getBitmap());
    }
}
