package jp.co.c_lis.ccl.maptracker.android.ui;

import java.util.List;

import jp.co.c_lis.ccl.maptracker.android.R;
import jp.co.c_lis.ccl.maptracker.android.util.DBManager;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class MainActivity extends MapActivity {
    private static final boolean DEBUG_FLAG = true;
    private static final String LOG_TAG = "MainActivity";

    private static final int E6 = 1000000;

    // マップの初期位置
    private static final GeoPoint FIRST_POINT = new GeoPoint(34697332, 135516577);

    // マップの初期拡大率
    private static final int FIRST_ZOOM_LEVEL = 8;

    // 地図に表示するマーカーの最大数
    private static final int LIMIT = 100;

    // テーブルのカラム
    private static final String[] mProjection
            = new String[] {
                    "_id",
                    "time",
                    "latitude",
                    "longitude",
                    };

    /**
     * マップ上に重ねるオーバーレイ
     */
    private class LocationOverlay extends ItemizedOverlay<OverlayItem> {

        private Drawable mIcon = null;
        private Cursor cursor = null;

        /**
         * ＤＢの再読み込み
         */
        public void reloadDB() {
            this.cursor = mDb.query(DBManager.DB_LOCATION_TABLE,
                    mProjection,
                    null, null, null, null,
                    "time",
                    String.valueOf(LIMIT)
                    );

            // 要素の再構築
            populate();
        }

        /**
         * コンストラクタ
         * 
         * @param arg0
         */
        public LocationOverlay(Drawable arg0) {
            super(arg0);
            mIcon = arg0;
        }

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

        @Override
        protected OverlayItem createItem(int i) {
            if (cursor.moveToPosition(i)) {
                String title = String.valueOf(cursor.getLong(COLUMN_INDEX_TIME));
                String snippet = "";
                int latitudeE6 = (int) (cursor.getFloat(COLUMN_INDEX_LATITUDE) * E6);
                int longitudeE6 = (int) (cursor.getFloat(COLUMN_INDEX_LONGITUDE) * E6);

                 OverlayItem item = new OverlayItem(new GeoPoint(latitudeE6, longitudeE6),
                        title,
                        snippet);
                item.setMarker(mIcon);

                return item;
            }

            Log.e(LOG_TAG, "overlay is null");
            return null;
        }

    }

    // 各カラムのインデックス
    private static final int COLUMN_INDEX_ID = 0;
    private static final int COLUMN_INDEX_TIME = 1;
    private static final int COLUMN_INDEX_LATITUDE = 2;
    private static final int COLUMN_INDEX_LONGITUDE = 3;

    /**
     * 位置情報の更新を処理するリスナー
     */
    private LocationListener mListener = new LocationListener() {
        public void onStatusChanged(String provider, int status, Bundle extras) { }
        public void onProviderEnabled(String provider) { }
        public void onProviderDisabled(String provider) { }

        public void onLocationChanged(Location location) {

            // 位置情報をログに出力
            if (DEBUG_FLAG) MainActivity.showLocationLog(location);

            // 位置情報をDBに保存
            saveLocation(location);

            // マップに表示
            mLocationOverlay.reloadDB();
            
            // 取得した位置を、マップの中心を設定
            mMapController.setCenter(new GeoPoint(
                    (int) (location.getLatitude() * E6),
                    (int) (location.getLongitude() * E6)));
        }
    };

    /**
     * 位置情報をログに表示
     * 
     * @param location
     */
    private static void showLocationLog(Location location) {
        Log.d(LOG_TAG, "====================");
        Log.d(LOG_TAG, "time = " + System.currentTimeMillis());
        Log.d(LOG_TAG, "longitude = " + location.getLongitude());
        Log.d(LOG_TAG, "latitude = " + location.getLatitude());
        Log.d(LOG_TAG, "====================");
    }

    /**
     * 位置情報をDBに保存
     * 
     * @param location
     */
    private void saveLocation(Location location) {
        ContentValues values = new ContentValues();
        values.put("time", System.currentTimeMillis());
        values.put("latitude", location.getLatitude());
        values.put("longitude", location.getLongitude());
        mDb.insert(DBManager.DB_LOCATION_TABLE, null, values);
    }

    private SQLiteDatabase mDb = null;
    private MapView mMapView = null;
    private MapController mMapController = null;
    private LocationOverlay mLocationOverlay = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        DBManager dbManager = new DBManager(this,
                DBManager.DB_FILE_NAME,
                null,
                DBManager.DB_VERSION);
        mDb = dbManager.getWritableDatabase();

        mMapView = (MapView) findViewById(R.id.main_map);
        mMapView.setClickable(true);
        mMapView.setBuiltInZoomControls(true);

        mMapController = mMapView.getController();
        mMapController.animateTo(FIRST_POINT);
        mMapController.setZoom(FIRST_ZOOM_LEVEL);

        Drawable pin = getResources().getDrawable(R.drawable.icon);
        pin.setBounds(0, 0, pin.getMinimumWidth(), pin.getMinimumHeight());
        mLocationOverlay = new LocationOverlay(pin);

        // 位置情報をマップに表示
        mLocationOverlay.reloadDB();

        List<Overlay> overlays = mMapView.getOverlays();
        overlays.add(mLocationOverlay);

        // 位置情報の取得を開始
        mLocationManager = ((LocationManager) getSystemService(Context.LOCATION_SERVICE));
        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, LOCATION_MIN_TIME,
                LOCATION_MIN_DISTANCE, mListener);

    }

    private LocationManager mLocationManager = null;
    private static final long LOCATION_MIN_TIME = 1000 * 60;
    private static final float LOCATION_MIN_DISTANCE = 5.0F;

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

        // 位置情報の取得を終了
        mLocationManager.removeUpdates(mListener);

        // DBを閉じる
        mDb.close();
    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
}