/*
 * Copyright (C) 2014 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.fmradio;

import android.app.ActionBar;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.location.Location;
import android.location.LocationManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.android.fmradio.FmService.OnExitListener;
import com.android.fmradio.FmStation.Station;

/**
 * This class interact with user, provider edit station information, such as add
 * to favorite, edit favorite, delete from favorite
 */
public class FmFavoriteActivity extends Activity {
    // Logging
    private static final String TAG = "FmFavoriteActivity";

    public static final String ACTIVITY_RESULT = "ACTIVITY_RESULT";

    private static final String SHOW_GPS_DIALOG = "SHOW_GPS_DIALOG";

    private static final String GPS_NOT_LOCATED_DIALOG = "GPS_NOT_LOCATED_DIALOG";

    private ListView mLvFavorites = null; // list view

    LinearLayout mSearchTips = null;

    private Context mContext = null; // application context

    private OnExitListener mExitListener = null;

    private MyFavoriteAdapter mMyAdapter;

    private ProgressBar mSearchProgress = null;

    private MenuItem mMenuRefresh = null;

    private LocationManager mLocationManager;

    private Location mCurLocation;

    private boolean mIsActivityForeground = true;

    /**
     * on create
     *
     * @param savedInstanceState The save instance state
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Bind the activity to FM audio stream.
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
        setContentView(R.layout.favorite);
        // display action bar and navigation button
        ActionBar actionBar = getActionBar();
        actionBar.setTitle(getString(R.string.station_title));
        actionBar.setDisplayHomeAsUpEnabled(true);
        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        mContext = getApplicationContext();

        mMyAdapter = new MyFavoriteAdapter(mContext);
        mLvFavorites = (ListView) findViewById(R.id.station_list);
        mSearchTips = (LinearLayout) findViewById(R.id.search_tips);
        mSearchProgress = (ProgressBar) findViewById(R.id.search_progress);
        mLvFavorites.setAdapter(mMyAdapter); // set adapter
        mMyAdapter.swipResult(getData());

        mLvFavorites.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            /**
             * Click list item will finish activity and pass value to other activity
             *
             * @param parent adapter view
             * @param view item view
             * @param position current position
             * @param id current id
             */
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // Set the selected frequency to main UI and finish the
                // favorite manager.
                TextView textView = (TextView) view.findViewById(R.id.lv_station_freq);
                float frequency = 0;
                try {
                    frequency = Float.parseFloat(textView.getText().toString());
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
                Intent intentResult = new Intent();
                intentResult.putExtra(ACTIVITY_RESULT, FmUtils.computeStation(frequency));
                setResult(RESULT_OK, intentResult);
                finish();
            }
        });

        // Finish favorite when exit FM
        mExitListener = new FmService.OnExitListener() {
            @Override
            public void onExit() {
                Handler mainHandler = new Handler(Looper.getMainLooper());
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        FmFavoriteActivity.this.finish();
                    }
                });
            }
        };
        FmService.registerExitListener(mExitListener);
        if (!mIsServiceBinded) {
            bindService();
        }
    }

    /**
     * When menu is selected
     *
     * @param item The selected menu item
     * @return true to consume it, false to can handle other
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
            case R.id.fm_station_list_refresh:
                if (null != mService) {
                    refreshMenuItem(false);

                    mMyAdapter.swipResult(null);
                    mLvFavorites.setEmptyView(mSearchTips);
                    mSearchProgress.setIndeterminate(true);

                    // If current location and last location exceed defined distance, delete the RDS database
                    if (isGpsOpen()) {
                        mCurLocation = mLocationManager
                                .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                        if (mCurLocation != null) {
                            double[] lastLocations = FmUtils.getLastSearchedLocation(mContext);
                            float distance[] = new float[2];
                            Location.distanceBetween(lastLocations[0], lastLocations[1],
                                    mCurLocation.getLatitude(), mCurLocation.getLongitude(),
                                    distance);
                            float searchedDistance = distance[0];
                            boolean exceed =
                                    searchedDistance > FmUtils.LOCATION_DISTANCE_EXCEED;
                            mService.setDistanceExceed(exceed);
                            FmUtils.setLastSearchedLocation(mContext, mCurLocation.getLatitude(),
                                    mCurLocation.getLongitude());
                        }
                    }

                    mService.startScanAsync();
                }
                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        if (null == mService) {
            Log.w(TAG, "onBackPressed, mService is null");
        } else {
            boolean isScanning = mService.isScanning();
            if (isScanning) {
                mService.stopScan();
            }
        }
        super.onBackPressed();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.fm_station_list_menu, menu);
        mMenuRefresh = menu.findItem(R.id.fm_station_list_refresh);
        resetMenuTitleColor(true);
        return true;
    }

    private void resetMenuTitleColor(boolean enabled) {
        SpannableString ss = new SpannableString(mMenuRefresh.getTitle());
        int titleColor = enabled ? getResources().getColor(R.color.actionbar_overflow_title_color)
                : getResources().getColor(R.color.actionbar_overflow_title_disabled_color);
        ss.setSpan(new ForegroundColorSpan(titleColor), 0, ss.length(), 0);
        mMenuRefresh.setTitle(ss);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if (null != mService) {
            boolean isScan = mService.isScanning();
            refreshMenuItem(!isScan);
        }
        return super.onPrepareOptionsMenu(menu);
    }

    static final class ViewHolder {
        ImageView mStationTypeView;
        TextView mStationFreqView;
        TextView mStationNameView;
        TextView mStationRdsView;
        RelativeLayout mImgLayout;
    }

    private Cursor getData() {
        Cursor cursor = mContext.getContentResolver().query(Station.CONTENT_URI,
                FmStation.COLUMNS, null, null, FmStation.Station.FREQUENCY);
        return cursor;
    }

    class MyFavoriteAdapter extends BaseAdapter {
        private Cursor mCursor;

        private LayoutInflater mInflater;

        public MyFavoriteAdapter(Context context) {
            mInflater = LayoutInflater.from(context);
        }

        public void swipResult(Cursor cursor) {
            if (null != mCursor) {
                mCursor.close();
            }
            mCursor = cursor;
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            if (null != mCursor) {
                return mCursor.getCount();
            }
            return 0;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder = null;
            if (null == convertView) {
                viewHolder = new ViewHolder();
                convertView = mInflater.inflate(R.layout.station_item, null);
                viewHolder.mStationTypeView = (ImageView) convertView
                        .findViewById(R.id.lv_station_type);
                viewHolder.mStationFreqView = (TextView) convertView
                        .findViewById(R.id.lv_station_freq);
                viewHolder.mStationNameView = (TextView) convertView
                        .findViewById(R.id.lv_station_name);
                viewHolder.mStationRdsView = (TextView) convertView
                        .findViewById(R.id.lv_station_rds);
                viewHolder.mImgLayout = (RelativeLayout) convertView
                        .findViewById(R.id.list_item_right);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            if (mCursor != null && mCursor.moveToFirst()) {
                mCursor.moveToPosition(position);
                final int stationFreq = mCursor.getInt(mCursor
                        .getColumnIndex(FmStation.Station.FREQUENCY));
                String name = mCursor.getString(mCursor
                        .getColumnIndex(FmStation.Station.STATION_NAME));
                String rds = mCursor.getString(mCursor
                        .getColumnIndex(FmStation.Station.RADIO_TEXT));
                final int isFavorite = mCursor.getInt(mCursor
                        .getColumnIndex(FmStation.Station.IS_FAVORITE));

                if (null == name || "".equals(name)) {
                    name = mCursor.getString(mCursor
                            .getColumnIndex(FmStation.Station.PROGRAM_SERVICE));
                }

                if (rds == null || rds.equals("")) {
                    viewHolder.mStationRdsView.setVisibility(View.GONE);
                } else {
                    viewHolder.mStationRdsView.setVisibility(View.VISIBLE);
                }

                viewHolder.mStationFreqView.setText(FmUtils.formatStation(stationFreq));
                viewHolder.mStationNameView.setText(name);
                viewHolder.mStationRdsView.setText(rds);
                if (0 == isFavorite) {
                    viewHolder.mStationTypeView.setImageResource(R.drawable.btn_fm_favorite_off);
                    viewHolder.mStationTypeView.setColorFilter(Color.BLACK,
                            PorterDuff.Mode.SRC_ATOP);
                    viewHolder.mStationTypeView.setAlpha(0.54f);
                } else {
                    viewHolder.mStationTypeView.setImageResource(R.drawable.btn_fm_favorite_on);
                    viewHolder.mStationTypeView.setColorFilter(null);
                    viewHolder.mStationTypeView.setAlpha(1.0f);
                }

                viewHolder.mImgLayout.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (0 == isFavorite) {
                            addFavorite(stationFreq);
                        } else {
                            deleteFavorite(stationFreq);
                        }
                    }
                });
            }
            return convertView;
        }
    }

    /**
     * Add searched station as favorite station
     */
    public void addFavorite(int stationFreq) {
        // TODO it's on UI thread, change to sub thread
        // update the station name and station type in database
        // according the frequency
        FmStation.addToFavorite(mContext, stationFreq);
        mMyAdapter.swipResult(getData());
    }

    /**
     * Delete favorite from favorite station list, make it as searched station
     */
    public void deleteFavorite(int stationFreq) {
        // TODO it's on UI thread, change to sub thread
        // update the station type from favorite to searched.
        FmStation.removeFromFavorite(mContext, stationFreq);
        mMyAdapter.swipResult(getData());
    }

    @Override
    protected void onResume() {
        super.onResume();
        mIsActivityForeground = true;
        if (null != mService) {
            mService.setFmMainActivityForeground(mIsActivityForeground);
            if (FmRecorder.STATE_RECORDING != mService.getRecorderState()) {
                mService.removeNotification();
            }
        }
    }

    @Override
    protected void onPause() {
        mIsActivityForeground = false;
        if (null != mService) {
            mService.setFmMainActivityForeground(mIsActivityForeground);
        }
        super.onPause();
    }

    @Override
    protected void onStop() {
       // FmUtils.updateFrontActivity(mContext, "");
        if (null != mService) {
            // home key pressed, show notification
            mService.setNotificationClsName(FmFavoriteActivity.class.getName());
            mService.updatePlayingNotification();
        }
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        mMyAdapter.swipResult(null);
        FmService.unregisterExitListener(mExitListener);
        if (mService != null) {
            mService.unregisterFmRadioListener(mFmRadioListener);
        }
        unbindService();
        super.onDestroy();
    }

    private FmService mService = null;

    private boolean mIsServiceBinded = false;

    private void bindService() {
        mIsServiceBinded = bindService(new Intent(FmFavoriteActivity.this, FmService.class),
                mServiceConnection, Context.BIND_AUTO_CREATE);
        if (!mIsServiceBinded) {
            Log.e(TAG, "bindService, mIsServiceBinded is false");
            finish();
        }
    }

    private void unbindService() {
        if (mIsServiceBinded) {
            unbindService(mServiceConnection);
        }
    }

    // Service listener
    private FmListener mFmRadioListener = new FmListener() {
        @Override
        public void onCallBack(Bundle bundle) {
            int flag = bundle.getInt(FmListener.CALLBACK_FLAG);
            if (flag == FmListener.MSGID_FM_EXIT) {
                mHandler.removeCallbacksAndMessages(null);
            }

            // remove tag message first, avoid too many same messages in queue.
            Message msg = mHandler.obtainMessage(flag);
            msg.setData(bundle);
            mHandler.removeMessages(flag);
            mHandler.sendMessage(msg);
        }
    };

    /**
     * Main thread handler to update UI
     */
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Log.d(TAG,
                    "handleMessage, what = " + msg.what + ",hashcode:"
                            + mHandler.hashCode());
            Bundle bundle;
            switch (msg.what) {
                case FmListener.MSGID_SCAN_FINISHED:
                    bundle = msg.getData();
                    // cancel scan happen
                    boolean isScan = bundle.getBoolean(FmListener.KEY_IS_SCAN);
                    int searchedNum = bundle.getInt(FmListener.KEY_STATION_NUM);
                    refreshMenuItem(true);
                    mMyAdapter.swipResult(getData());
                    mService.updatePlayingNotification();
                    if (searchedNum == 0) {
                        Toast.makeText(mContext, getString(R.string.toast_cannot_search),
                                Toast.LENGTH_SHORT).show();
                        // searched station is zero, if db has station, should not use empty.
                        if (mMyAdapter.getCount() == 0) {
                            View emptyView = (View) findViewById(R.id.empty_tips);
                            emptyView.setVisibility(View.VISIBLE);
                            View searchTips = (View) findViewById(R.id.search_tips);
                            searchTips.setVisibility(View.GONE);
                        }
                        return;
                    }
                    // Show toast to tell user how many stations have been searched
                    String text = getString(R.string.toast_station_searched) + " "
                            + String.valueOf(searchedNum);
                    Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
                    break;
                case FmListener.MSGID_SWITCH_ANTENNA:
                    bundle = msg.getData();
                    boolean isHeadset = bundle.getBoolean(FmListener.KEY_IS_SWITCH_ANTENNA);
                    // if receive headset plugout, need set headset mode on ui
                    if (!isHeadset) {
                        finish();
                    }
                    break;
                default:
                    break;
            }
        }
    };

    private void refreshMenuItem(boolean enabled) {
        // action menu
        if (mMenuRefresh != null) {
            mMenuRefresh.setEnabled(enabled);
            resetMenuTitleColor(enabled);
        }
    }

    // When call bind service, it will call service connect. register call back
    // listener and initial device
    private final ServiceConnection mServiceConnection = new ServiceConnection() {

        /**
         * called by system when bind service
         *
         * @param className component name
         * @param service service binder
         */
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = ((FmService.ServiceBinder) service).getService();
            if (null == mService) {
                Log.e(TAG, "onServiceConnected, mService is null");
                finish();
                return;
            }
            mService.registerFmRadioListener(mFmRadioListener);
            mService.setFmMainActivityForeground(mIsActivityForeground);
            if (FmRecorder.STATE_RECORDING != mService.getRecorderState()) {
                mService.removeNotification();
            }
            // FmUtils.isFirstEnterStationList() must be called at the first time.
            // After it is called, it will save status to SharedPreferences.
            if (FmUtils.isFirstEnterStationList(mContext) || (0 == mMyAdapter.getCount())) {
                refreshMenuItem(false);
                mLvFavorites.setEmptyView(mSearchTips);
                mSearchProgress.setIndeterminate(true);
                mMyAdapter.swipResult(null);
                mService.startScanAsync();
            } else {
                boolean isScan = mService.isScanning();
                if (isScan) {
                    mMyAdapter.swipResult(null);
                    mLvFavorites.setEmptyView(mSearchTips);
                    mSearchProgress.setIndeterminate(true);
                } else {
                    // TODO it's on UI thread, change to sub thread
                    mMyAdapter.swipResult(getData());
                }
                refreshMenuItem(!isScan);
            }
        }

        /**
         * When unbind service will call this method
         *
         * @param className The component name
         */
        @Override
        public void onServiceDisconnected(ComponentName className) {
        }
    };

    /**
     * check gps is open or not
     *
     * @return true is open
     */
    private boolean isGpsOpen() {
        return mLocationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);
    }
}
