/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.car.radio;

import android.annotation.Nullable;
import android.content.Intent;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.util.Pair;

import androidx.car.drawer.CarDrawerActivity;
import androidx.car.drawer.CarDrawerAdapter;
import androidx.car.drawer.DrawerItemViewHolder;

import java.util.ArrayList;
import java.util.List;

/**
 * The main activity for the radio. This activity initializes the radio controls and listener for
 * radio changes.
 */
public class CarRadioActivity extends CarDrawerActivity implements
        RadioPresetsFragment.PresetListExitListener,
        MainRadioFragment.RadioPresetListClickListener,
        ManualTunerFragment.ManualTunerCompletionListener {
    private static final String TAG = "Em.RadioActivity";
    private static final String MANUAL_TUNER_BACKSTACK = "MANUAL_TUNER_BACKSTACK";
    private static final String CONTENT_FRAGMENT_TAG = "CONTENT_FRAGMENT_TAG";

    private static final List<Pair<Integer, String>> SUPPORTED_RADIO_BANDS = new ArrayList<>();

    /**
     * Intent action for notifying that the radio state has changed.
     */
    private static final String ACTION_RADIO_APP_STATE_CHANGE
            = "android.intent.action.RADIO_APP_STATE_CHANGE";

    /**
     * Boolean Intent extra indicating if the radio is the currently in the foreground.
     */
    private static final String EXTRA_RADIO_APP_FOREGROUND
            = "android.intent.action.RADIO_APP_STATE";

    /**
     * Whether or not it is safe to make transactions on the
     * {@link android.support.v4.app.FragmentManager}. This variable prevents a possible exception
     * when calling commit() on the FragmentManager.
     *
     * <p>The default value is {@code true} because it is only after
     * {@link #onSaveInstanceState(Bundle)} has been called that fragment commits are not allowed.
     */
    private boolean mAllowFragmentCommits = true;

    private RadioController mRadioController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        SUPPORTED_RADIO_BANDS.add(
                new Pair<>(RadioManager.BAND_AM, getString(R.string.radio_am_text)));
        SUPPORTED_RADIO_BANDS.add(
                new Pair<>(RadioManager.BAND_FM, getString(R.string.radio_fm_text)));

        super.onCreate(savedInstanceState);
        setToolbarElevation(0f);

        mRadioController = new RadioController(this);
        setContentFragment(
                MainRadioFragment.newInstance(mRadioController, this /* clickListener */));

    }

    @Override
    protected CarDrawerAdapter getRootAdapter() {
        return new RadioDrawerAdapter();
    }

    @Override
    public void onPresetListClicked() {
        setContentFragment(
                RadioPresetsFragment.newInstance(mRadioController, this /* existListener */));
    }

    @Override
    public void OnPresetListExit() {
        setContentFragment(
                MainRadioFragment.newInstance(mRadioController, this /* clickListener */));
    }

    private void startManualTuner() {
        if (!mAllowFragmentCommits || getSupportFragmentManager().getBackStackEntryCount() > 0) {
            return;
        }

        Fragment currentFragment = getCurrentFragment();
        if (currentFragment instanceof FragmentWithFade) {
            ((FragmentWithFade) currentFragment).fadeOutContent();
        }

        ManualTunerFragment tunerFragment =
                ManualTunerFragment.newInstance(mRadioController.getCurrentRadioBand());
        tunerFragment.setManualTunerCompletionListener(this);

        getSupportFragmentManager().beginTransaction()
                .setCustomAnimations(R.anim.slide_up, R.anim.slide_down,
                        R.anim.slide_up, R.anim.slide_down)
                .add(getContentContainerId(), tunerFragment)
                .addToBackStack(MANUAL_TUNER_BACKSTACK)
                .commit();
    }

    @Override
    public void onStationSelected(ProgramSelector sel) {
        maybeDismissManualTuner();

        Fragment fragment = getCurrentFragment();
        if (fragment instanceof FragmentWithFade) {
            ((FragmentWithFade) fragment).fadeInContent();
        }

        if (sel != null) {
            mRadioController.tune(sel);
        }
    }

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

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onStart");
        }

        // Fragment commits are not allowed once the Activity's state has been saved. Once
        // onStart() has been called, the FragmentManager should now allow commits.
        mAllowFragmentCommits = true;

        mRadioController.start();

        Intent broadcast = new Intent(ACTION_RADIO_APP_STATE_CHANGE);
        broadcast.putExtra(EXTRA_RADIO_APP_FOREGROUND, true);
        sendBroadcast(broadcast);
    }

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

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onStop");
        }

        Intent broadcast = new Intent(ACTION_RADIO_APP_STATE_CHANGE);
        broadcast.putExtra(EXTRA_RADIO_APP_FOREGROUND, false);
        sendBroadcast(broadcast);
    }

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

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDestroy");
        }

        mRadioController.shutdown();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // A transaction can only be committed with this method prior to its containing activity
        // saving its state.
        mAllowFragmentCommits = false;
        super.onSaveInstanceState(outState);
    }

    /**
     * Checks if the manual tuner is currently being displayed. If it is, then dismiss it.
     */
    private void maybeDismissManualTuner() {
        FragmentManager fragmentManager = getSupportFragmentManager();
        if (fragmentManager.getBackStackEntryCount() > 0) {
            // A station can only be selected if the manual tuner fragment has been shown; so, remove
            // that here.
            getSupportFragmentManager().popBackStack();
        }
    }

    private void setContentFragment(Fragment fragment) {
        if (!mAllowFragmentCommits) {
            return;
        }

        getSupportFragmentManager().beginTransaction()
                .replace(getContentContainerId(), fragment, CONTENT_FRAGMENT_TAG)
                .commitNow();
    }

    /**
     * Returns the fragment that is currently being displayed as the content view. Note that this
     * is not necessarily the fragment that is visible. The manual tuner fragment can be displayed
     * on top of this content fragment.
     */
    @Nullable
    private Fragment getCurrentFragment() {
        return getSupportFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG);
    }

    /**
     * An adapter that is responsible for populating the Radio drawer with the available bands to
     * select, as well as the option for opening the manual tuner.
     */
    private class RadioDrawerAdapter extends CarDrawerAdapter {
        private final List<String> mDrawerOptions =
                new ArrayList<>(SUPPORTED_RADIO_BANDS.size() + 1);

        RadioDrawerAdapter() {
            super(CarRadioActivity.this, false /* showDisabledListOnEmpty */);
            setTitle(getString(R.string.app_name));
            // The ordering of options is hardcoded. The click handler below depends on it.
            for (Pair<Integer, String> band : SUPPORTED_RADIO_BANDS) {
                mDrawerOptions.add(band.second);
            }
            mDrawerOptions.add(getString(R.string.manual_tuner_drawer_entry));
        }

        @Override
        protected int getActualItemCount() {
            return mDrawerOptions.size();
        }

        @Override
        public void populateViewHolder(DrawerItemViewHolder holder, int position) {
            holder.getTitle().setText(mDrawerOptions.get(position));
        }

        @Override
        public void onItemClick(int position) {
            getDrawerController().closeDrawer();
            if (position < SUPPORTED_RADIO_BANDS.size()) {
                mRadioController.switchBand(SUPPORTED_RADIO_BANDS.get(position).first);
            } else if (position == SUPPORTED_RADIO_BANDS.size()) {
                startManualTuner();
            } else {
                Log.w(TAG, "Unexpected position: " + position);
            }
        }
    }
}
