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

import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import javax.microedition.khronos.egl.*;
import javax.microedition.khronos.opengles.*;

import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.opengl.Object3D;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;

/**
 * The main View of the GlobalTime Activity.
 */
class GTView extends SurfaceView implements SurfaceHolder.Callback {

    /**
     * A TimeZone object used to compute the current UTC time.
     */
    private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("utc");

    /**
     * The Sun's color is close to that of a 5780K blackbody.
     */
    private static final float[] SUNLIGHT_COLOR = {
        1.0f, 0.9375f, 0.91015625f, 1.0f
    };

    /**
     * The inclination of the earth relative to the plane of the ecliptic
     * is 23.45 degrees.
     */
    private static final float EARTH_INCLINATION = 23.45f * Shape.PI / 180.0f;

    /** Seconds in a day */
    private static final int SECONDS_PER_DAY = 24 * 60 * 60;

    /** Flag for the depth test */
    private static final boolean PERFORM_DEPTH_TEST= false;

    /** Use raw time zone offsets, disregarding "summer time."  If false,
     * current offsets will be used, which requires a much longer startup time
     * in order to sort the city database.
     */
    private static final boolean USE_RAW_OFFSETS = true;

    /**
     * The earth's atmosphere.
     */
    private static final Annulus ATMOSPHERE =
        new Annulus(0.0f, 0.0f, 1.75f, 0.9f, 1.08f, 0.4f, 0.4f, 0.8f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f, 50);

    /**
     * The tesselation of the earth by latitude.
     */
    private static final int SPHERE_LATITUDES = 25;

    /**
     * The tesselation of the earth by longitude.
     */
    private static int SPHERE_LONGITUDES = 25;

    /**
     * A flattened version of the earth.  The normals are computed identically
     * to those of the round earth, allowing the day/night lighting to be
     * applied to the flattened surface.
     */
    private static Sphere worldFlat = new LatLongSphere(0.0f, 0.0f, 0.0f, 1.0f,
        SPHERE_LATITUDES, SPHERE_LONGITUDES,
        0.0f, 360.0f, true, true, false, true);

    /**
     * The earth.
     */
    private Object3D mWorld;

    /**
     * Geometry of the city lights
     */
    private PointCloud mLights;

    /**
     * True if the activiy has been initialized.
     */
    boolean mInitialized = false;

    /**
     * True if we're in alphabetic entry mode.
     */
    private boolean mAlphaKeySet = false;

    private EGLContext mEGLContext;
    private EGLSurface mEGLSurface;
    private EGLDisplay mEGLDisplay;
    private EGLConfig  mEGLConfig;
    GLView  mGLView;

    // Rotation and tilt of the Earth
    private float mRotAngle = 0.0f;
    private float mTiltAngle = 0.0f;

    // Rotational velocity of the orbiting viewer
    private float mRotVelocity = 1.0f;

    // Rotation of the flat view
    private float mWrapX =  0.0f;
    private float  mWrapVelocity =  0.0f;
    private float mWrapVelocityFactor =  0.01f;

    // Toggle switches
    private boolean mDisplayAtmosphere = true;
    private boolean mDisplayClock = false;
    private boolean mClockShowing = false;
    private boolean mDisplayLights = false;
    private boolean mDisplayWorld = true;
    private boolean mDisplayWorldFlat = false;
    private boolean mSmoothShading = true;

    // City search string
    private String mCityName = "";

    // List of all cities
    private List<City> mClockCities;

    // List of cities matching a user-supplied prefix
    private List<City> mCityNameMatches = new ArrayList<City>();

    private List<City> mCities;

    // Start time for clock fade animation
    private long mClockFadeTime;

    // Interpolator for clock fade animation
    private Interpolator mClockSizeInterpolator =
        new DecelerateInterpolator(1.0f);

    // Index of current clock
    private int mCityIndex;

    // Current clock
    private Clock mClock;

    // City-to-city flight animation parameters
    private boolean mFlyToCity = false;
    private long mCityFlyStartTime;
    private float mCityFlightTime;
    private float mRotAngleStart, mRotAngleDest;
    private float mTiltAngleStart, mTiltAngleDest;

    // Interpolator for flight motion animation
    private Interpolator mFlyToCityInterpolator =
        new AccelerateDecelerateInterpolator();

    private static int sNumLights;
    private static int[] sLightCoords;

    //     static Map<Float,int[]> cityCoords = new HashMap<Float,int[]>();

    // Arrays for GL calls
    private float[] mClipPlaneEquation = new float[4];
    private float[] mLightDir = new float[4];

    // Calendar for computing the Sun's position
    Calendar mSunCal = Calendar.getInstance(UTC_TIME_ZONE);

    // Triangles drawn per frame
    private int mNumTriangles;

    private long startTime;

    private static final int MOTION_NONE = 0;
    private static final int MOTION_X = 1;
    private static final int MOTION_Y = 2;

    private static final int MIN_MANHATTAN_DISTANCE = 20;
    private static final float ROTATION_FACTOR = 1.0f / 30.0f;
    private static final float TILT_FACTOR = 0.35f;

    // Touchscreen support
    private float mMotionStartX;
    private float mMotionStartY;
    private float mMotionStartRotVelocity;
    private float mMotionStartTiltAngle;
    private int mMotionDirection;
    
    private boolean mPaused = true;
    private boolean mHaveSurface = false;
    private boolean mStartAnimating = false;
    
    public void surfaceCreated(SurfaceHolder holder) {
        mHaveSurface = true;
        startEGL();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        mHaveSurface = false;
        stopEGL();
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // nothing to do
    }

    /**
     * Set up the view.
     *
     * @param context the Context
     * @param am an AssetManager to retrieve the city database from
     */
    public GTView(Context context) {
        super(context);

        getHolder().addCallback(this);
        getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);

        startTime = System.currentTimeMillis();

        mClock = new Clock();

        startEGL();
        
        setFocusable(true);
        setFocusableInTouchMode(true);
        requestFocus();
    }

    /**
     * Creates an egl context. If the state of the activity is right, also
     * creates the egl surface. Otherwise the surface will be created in a
     * future call to createEGLSurface().
     */
    private void startEGL() {
        EGL10 egl = (EGL10)EGLContext.getEGL();

        if (mEGLContext == null) {
            EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
            int[] version = new int[2];
            egl.eglInitialize(dpy, version);
            int[] configSpec = {
                    EGL10.EGL_DEPTH_SIZE,   16,
                    EGL10.EGL_NONE
            };
            EGLConfig[] configs = new EGLConfig[1];
            int[] num_config = new int[1];
            egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config);
            mEGLConfig = configs[0];

            mEGLContext = egl.eglCreateContext(dpy, mEGLConfig, 
                    EGL10.EGL_NO_CONTEXT, null);
            mEGLDisplay = dpy;
            
            AssetManager am = mContext.getAssets();
            try {
                loadAssets(am);
            } catch (IOException ioe) {
                ioe.printStackTrace();
                throw new RuntimeException(ioe);
            } catch (ArrayIndexOutOfBoundsException aioobe) {
                aioobe.printStackTrace();
                throw new RuntimeException(aioobe);
            }
        }
        
        if (mEGLSurface == null && !mPaused && mHaveSurface) {
            mEGLSurface = egl.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, 
                    this, null);
            egl.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, 
                    mEGLContext);
            mInitialized = false;
            if (mStartAnimating) {
                startAnimating();
                mStartAnimating = false;
            }
        }
    }
    
    /**
     * Destroys the egl context. If an egl surface has been created, it is
     * destroyed as well.
     */
    private void stopEGL() {
        EGL10 egl = (EGL10)EGLContext.getEGL();
        if (mEGLSurface != null) {
            egl.eglMakeCurrent(mEGLDisplay, 
                    egl.EGL_NO_SURFACE, egl.EGL_NO_SURFACE, egl.EGL_NO_CONTEXT);
            egl.eglDestroySurface(mEGLDisplay, mEGLSurface);
            mEGLSurface = null;
        }

        if (mEGLContext != null) {
            egl.eglDestroyContext(mEGLDisplay, mEGLContext);
            egl.eglTerminate(mEGLDisplay);
            mEGLContext = null;
            mEGLDisplay = null;
            mEGLConfig = null;
        }
    }
    
    public void onPause() {
        mPaused = true;
        stopAnimating();
        stopEGL();
    }
    
    public void onResume() {
        mPaused = false;
        startEGL();
    }
    
    public void destroy() {
        stopAnimating();
        stopEGL();
    }

    /**
     * Begin animation.
     */
    public void startAnimating() {
        if (mEGLSurface == null) {
            mStartAnimating = true; // will start when egl surface is created
        } else {
            mHandler.sendEmptyMessage(INVALIDATE);
        }
    }

    /**
     * Quit animation.
     */
    public void stopAnimating() {
        mHandler.removeMessages(INVALIDATE);
    }

    /**
     * Read a two-byte integer from the input stream.
     */
    private int readInt16(InputStream is) throws IOException {
        int lo = is.read();
        int hi = is.read();
        return (hi << 8) | lo;
    }

    /**
     * Returns the offset from UTC for the given city.  If USE_RAW_OFFSETS
     * is true, summer/daylight savings is ignored.
     */
    private static float getOffset(City c) {
        return USE_RAW_OFFSETS ? c.getRawOffset() : c.getOffset();
    }

    private InputStream cache(InputStream is) throws IOException {
        int nbytes = is.available();
        byte[] data = new byte[nbytes];
        int nread = 0;
        while (nread < nbytes) {
            nread += is.read(data, nread, nbytes - nread);
        }
        return new ByteArrayInputStream(data);
    }

    /**
     * Load the city and lights databases.
     *
     * @param am the AssetManager to load from.
     */
    private void loadAssets(final AssetManager am) throws IOException {
        Locale locale = Locale.getDefault();
        String language = locale.getLanguage();
        String country = locale.getCountry();

        InputStream cis = null;
        try {
            // Look for (e.g.) cities_fr_FR.dat or cities_fr_CA.dat
            cis = am.open("cities_" + language + "_" + country + ".dat");
        } catch (FileNotFoundException e1) {
            try {
                // Look for (e.g.) cities_fr.dat or cities_fr.dat
                cis = am.open("cities_" + language + ".dat");
            } catch (FileNotFoundException e2) {
                try {
                    // Use English city names by default
                    cis = am.open("cities_en.dat");
                } catch (FileNotFoundException e3) {
                    throw e3;
                }
            }
        }

        cis = cache(cis);
        City.loadCities(cis);
        City[] cities;
        if (USE_RAW_OFFSETS) {
            cities = City.getCitiesByRawOffset();
        } else {
            cities = City.getCitiesByOffset();
        }

        mClockCities = new ArrayList<City>(cities.length);
        for (int i = 0; i < cities.length; i++) {
            mClockCities.add(cities[i]);
        }
        mCities = mClockCities;
        mCityIndex = 0;

        this.mWorld = new Object3D() {
                @Override
                public InputStream readFile(String filename)
                    throws IOException {
                    return cache(am.open(filename));
                }
            };

        mWorld.load("world.gles");

        // lights.dat has the following format.  All integers
        // are 16 bits, low byte first.
        //
        // width
        // height
        // N [# of lights]
        // light 0 X [in the range 0 to (width - 1)]
        // light 0 Y ]in the range 0 to (height - 1)]
        // light 1 X [in the range 0 to (width - 1)]
        // light 1 Y ]in the range 0 to (height - 1)]
        // ...
        // light (N - 1) X [in the range 0 to (width - 1)]
        // light (N - 1) Y ]in the range 0 to (height - 1)]
        //
        // For a larger number of lights, it could make more
        // sense to store the light positions in a bitmap
        // and extract them manually
        InputStream lis = am.open("lights.dat");
        lis = cache(lis);

        int lightWidth = readInt16(lis);
        int lightHeight = readInt16(lis);
        sNumLights = readInt16(lis);
        sLightCoords = new int[3 * sNumLights];

        int lidx = 0;
        float lightRadius = 1.009f;
        float lightScale = 65536.0f * lightRadius;

        float[] cosTheta = new float[lightWidth];
        float[] sinTheta = new float[lightWidth];
        float twoPi = (float) (2.0 * Math.PI);
        float scaleW = twoPi / lightWidth;
        for (int i = 0; i < lightWidth; i++) {
            float theta = twoPi - i * scaleW;
            cosTheta[i] = (float)Math.cos(theta);
            sinTheta[i] = (float)Math.sin(theta);
        }

        float[] cosPhi = new float[lightHeight];
        float[] sinPhi = new float[lightHeight];
        float scaleH = (float) (Math.PI / lightHeight);
        for (int j = 0; j < lightHeight; j++) {
            float phi = j * scaleH;
            cosPhi[j] = (float)Math.cos(phi);
            sinPhi[j] = (float)Math.sin(phi);
        }

        int nbytes = 4 * sNumLights;
        byte[] ilights = new byte[nbytes];
        int nread = 0;
        while (nread < nbytes) {
            nread += lis.read(ilights, nread, nbytes - nread);
        }

        int idx = 0;
        for (int i = 0; i < sNumLights; i++) {
            int lx = (((ilights[idx + 1] & 0xff) << 8) |
                       (ilights[idx    ] & 0xff));
            int ly = (((ilights[idx + 3] & 0xff) << 8) |
                       (ilights[idx + 2] & 0xff));
            idx += 4;

            float sin = sinPhi[ly];
            float x = cosTheta[lx]*sin;
            float y = cosPhi[ly];
            float z = sinTheta[lx]*sin;

            sLightCoords[lidx++] = (int) (x * lightScale);
            sLightCoords[lidx++] = (int) (y * lightScale);
            sLightCoords[lidx++] = (int) (z * lightScale);
        }
        mLights = new PointCloud(sLightCoords);
    }

    /**
     * Returns true if two time zone offsets are equal.  We assume distinct
     * time zone offsets will differ by at least a few minutes.
     */
    private boolean tzEqual(float o1, float o2) {
        return Math.abs(o1 - o2) < 0.001;
    }

    /**
     * Move to a different time zone.
     *
     * @param incr The increment between the current and future time zones.
     */
    private void shiftTimeZone(int incr) {
        // If only 1 city in the current set, there's nowhere to go
        if (mCities.size() <= 1) {
            return;
        }

        float offset = getOffset(mCities.get(mCityIndex));
        do {
            mCityIndex = (mCityIndex + mCities.size() + incr) % mCities.size();
        } while (tzEqual(getOffset(mCities.get(mCityIndex)), offset));

        offset = getOffset(mCities.get(mCityIndex));
        locateCity(true, offset);
        goToCity();
    }

    /**
     * Returns true if there is another city within the current time zone
     * that is the given increment away from the current city.
     *
     * @param incr the increment, +1 or -1
     * @return
     */
    private boolean atEndOfTimeZone(int incr) {
        if (mCities.size() <= 1) {
            return true;
        }

        float offset = getOffset(mCities.get(mCityIndex));
        int nindex = (mCityIndex + mCities.size() + incr) % mCities.size();
        if (tzEqual(getOffset(mCities.get(nindex)), offset)) {
            return false;
        }
        return true;
    }

    /**
     * Shifts cities within the current time zone.
     *
     * @param incr the increment, +1 or -1
     */
    private void shiftWithinTimeZone(int incr) {
        float offset = getOffset(mCities.get(mCityIndex));
        int nindex = (mCityIndex + mCities.size() + incr) % mCities.size();
        if (tzEqual(getOffset(mCities.get(nindex)), offset)) {
            mCityIndex = nindex;
            goToCity();
        }
    }

    /**
     * Returns true if the city name matches the given prefix, ignoring spaces.
     */
    private boolean nameMatches(City city, String prefix) {
        String cityName = city.getName().replaceAll("[ ]", "");
        return prefix.regionMatches(true, 0,
                                    cityName, 0,
                                    prefix.length());
    }

    /**
     * Returns true if there are cities matching the given name prefix.
     */
    private boolean hasMatches(String prefix) {
        for (int i = 0; i < mClockCities.size(); i++) {
            City city = mClockCities.get(i);
            if (nameMatches(city, prefix)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Shifts to the nearest city that matches the new prefix.
     */
    private void shiftByName() {
        // Attempt to keep current city if it matches
        City finalCity = null;
        City currCity = mCities.get(mCityIndex);
        if (nameMatches(currCity, mCityName)) {
            finalCity = currCity;
        }

        mCityNameMatches.clear();
        for (int i = 0; i < mClockCities.size(); i++) {
            City city = mClockCities.get(i);
            if (nameMatches(city, mCityName)) {
                mCityNameMatches.add(city);
            }
        }

        mCities = mCityNameMatches;

        if (finalCity != null) {
            for (int i = 0; i < mCityNameMatches.size(); i++) {
                if (mCityNameMatches.get(i) == finalCity) {
                    mCityIndex = i;
                    break;
                }
            }
        } else {
            // Find the closest matching city
            locateCity(false, 0.0f);
        }
        goToCity();
    }

    /**
     * Increases or decreases the rotational speed of the earth.
     */
    private void incrementRotationalVelocity(float incr) {
        if (mDisplayWorldFlat) {
            mWrapVelocity -= incr;
        } else {
            mRotVelocity -= incr;
        }
    }

    /**
     * Clears the current matching prefix, while keeping the focus on
     * the current city.
     */
    private void clearCityMatches() {
        // Determine the global city index that matches the current city
        if (mCityNameMatches.size() > 0) {
            City city = mCityNameMatches.get(mCityIndex);
            for (int i = 0; i < mClockCities.size(); i++) {
                City ncity = mClockCities.get(i);
                if (city.equals(ncity)) {
                    mCityIndex = i;
                    break;
                }
            }
        }

        mCityName = "";
        mCityNameMatches.clear();
        mCities = mClockCities;
        goToCity();
    }

    /**
     * Fade the clock in or out.
     */
    private void enableClock(boolean enabled) {
        mClockFadeTime = System.currentTimeMillis();
        mDisplayClock = enabled;
        mClockShowing = true;
        mAlphaKeySet = enabled;
        if (enabled) {
            // Find the closest matching city
            locateCity(false, 0.0f);
        }
        clearCityMatches();
    }

    /**
     * Use the touchscreen to alter the rotational velocity or the
     * tilt of the earth.
     */
    @Override public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mMotionStartX = event.getX();
                mMotionStartY = event.getY();
                mMotionStartRotVelocity = mDisplayWorldFlat ?
                    mWrapVelocity : mRotVelocity;
                mMotionStartTiltAngle = mTiltAngle;

                // Stop the rotation
                if (mDisplayWorldFlat) {
                    mWrapVelocity = 0.0f;
                } else {
                    mRotVelocity = 0.0f;
                }
                mMotionDirection = MOTION_NONE;
                break;

            case MotionEvent.ACTION_MOVE:
                // Disregard motion events when the clock is displayed
                float dx = event.getX() - mMotionStartX;
                float dy = event.getY() - mMotionStartY;
                float delx = Math.abs(dx);
                float dely = Math.abs(dy);

                // Determine the direction of motion (major axis)
                // Once if has been determined, it's locked in until
                // we receive ACTION_UP or ACTION_CANCEL
                if ((mMotionDirection == MOTION_NONE) &&
                    (delx + dely > MIN_MANHATTAN_DISTANCE)) {
                    if (delx > dely) {
                        mMotionDirection = MOTION_X;
                    } else {
                        mMotionDirection = MOTION_Y;
                    }
                }

                // If the clock is displayed, don't actually rotate or tilt;
                // just use mMotionDirection to record whether motion occurred
                if (!mDisplayClock) {
                    if (mMotionDirection == MOTION_X) {
                        if (mDisplayWorldFlat) {
                            mWrapVelocity = mMotionStartRotVelocity +
                                dx * ROTATION_FACTOR;
                        } else {
                            mRotVelocity = mMotionStartRotVelocity +
                                dx * ROTATION_FACTOR;
                        }
                        mClock.setCity(null);
                    } else if (mMotionDirection == MOTION_Y &&
                        !mDisplayWorldFlat) {
                        mTiltAngle = mMotionStartTiltAngle + dy * TILT_FACTOR;
                        if (mTiltAngle < -90.0f) {
                            mTiltAngle = -90.0f;
                        }
                        if (mTiltAngle > 90.0f) {
                            mTiltAngle = 90.0f;
                        }
                        mClock.setCity(null);
                    }
                }
                break;

            case MotionEvent.ACTION_UP:
                mMotionDirection = MOTION_NONE;
                break;

            case MotionEvent.ACTION_CANCEL:
                mTiltAngle = mMotionStartTiltAngle;
                if (mDisplayWorldFlat) {
                    mWrapVelocity = mMotionStartRotVelocity;
                } else {
                    mRotVelocity = mMotionStartRotVelocity;
                }
                mMotionDirection = MOTION_NONE;
                break;
        }
        return true;
    }

    @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (mInitialized && mGLView.processKey(keyCode)) {
            boolean drawing = (mClockShowing || mGLView.hasMessages());
            this.setWillNotDraw(!drawing);
            return true;
        }

        boolean handled = false;

        // If we're not in alphabetical entry mode, convert letters
        // to their digit equivalents
        if (!mAlphaKeySet) {
            char numChar = event.getNumber();
            if (numChar >= '0' && numChar <= '9') {
                keyCode = KeyEvent.KEYCODE_0 + (numChar - '0');
            }
        }

        switch (keyCode) {
        // The 'space' key toggles the clock
        case KeyEvent.KEYCODE_SPACE:
            mAlphaKeySet = !mAlphaKeySet;
            enableClock(mAlphaKeySet);
            handled = true;
            break;

        // The 'left' and 'right' buttons shift time zones if the clock is
        // displayed, otherwise they alters the rotational speed of the earthh
        case KeyEvent.KEYCODE_DPAD_LEFT:
            if (mDisplayClock) {
                shiftTimeZone(-1);
            } else {
                mClock.setCity(null);
                incrementRotationalVelocity(1.0f);
            }
            handled = true;
            break;

        case KeyEvent.KEYCODE_DPAD_RIGHT:
            if (mDisplayClock) {
                shiftTimeZone(1);
            } else {
                mClock.setCity(null);
                incrementRotationalVelocity(-1.0f);
            }
            handled = true;
            break;

        // The 'up' and 'down' buttons shift cities within a time zone if the
        // clock is displayed, otherwise they tilt the earth
        case KeyEvent.KEYCODE_DPAD_UP:
            if (mDisplayClock) {
                shiftWithinTimeZone(-1);
            } else {
                mClock.setCity(null);
                if (!mDisplayWorldFlat) {
                    mTiltAngle += 360.0f / 48.0f;
                }
            }
            handled = true;
            break;

        case KeyEvent.KEYCODE_DPAD_DOWN:
            if (mDisplayClock) {
                shiftWithinTimeZone(1);
            } else {
                mClock.setCity(null);
                if (!mDisplayWorldFlat) {
                    mTiltAngle -= 360.0f / 48.0f;
                }
            }
            handled = true;
            break;

        // The center key stops the earth's rotation, then toggles between the
        // round and flat views of the earth
        case KeyEvent.KEYCODE_DPAD_CENTER:
            if ((!mDisplayWorldFlat && mRotVelocity == 0.0f) ||
                (mDisplayWorldFlat && mWrapVelocity == 0.0f)) {
                mDisplayWorldFlat = !mDisplayWorldFlat;
            } else {
                if (mDisplayWorldFlat) {
                    mWrapVelocity = 0.0f;
                } else {
                    mRotVelocity = 0.0f;
                }
            }
            handled = true;
            break;

        // The 'L' key toggles the city lights
        case KeyEvent.KEYCODE_L:
            if (!mAlphaKeySet && !mDisplayWorldFlat) {
                mDisplayLights = !mDisplayLights;
                handled = true;
            }
            break;


        // The 'W' key toggles the earth (just for fun)
        case KeyEvent.KEYCODE_W:
            if (!mAlphaKeySet && !mDisplayWorldFlat) {
                mDisplayWorld = !mDisplayWorld;
                handled = true;
            }
            break;

        // The 'A' key toggles the atmosphere
        case KeyEvent.KEYCODE_A:
            if (!mAlphaKeySet && !mDisplayWorldFlat) {
                mDisplayAtmosphere = !mDisplayAtmosphere;
                handled = true;
            }
            break;

        // The '2' key zooms out
        case KeyEvent.KEYCODE_2:
            if (!mAlphaKeySet && !mDisplayWorldFlat) {
                mGLView.zoom(-2);
                handled = true;
            }
            break;

        // The '8' key zooms in
        case KeyEvent.KEYCODE_8:
            if (!mAlphaKeySet && !mDisplayWorldFlat) {
                mGLView.zoom(2);
                handled = true;
            }
            break;
        }

        // Handle letters in city names
        if (!handled && mAlphaKeySet) {
            switch (keyCode) {
            // Add a letter to the city name prefix
            case KeyEvent.KEYCODE_A:
            case KeyEvent.KEYCODE_B:
            case KeyEvent.KEYCODE_C:
            case KeyEvent.KEYCODE_D:
            case KeyEvent.KEYCODE_E:
            case KeyEvent.KEYCODE_F:
            case KeyEvent.KEYCODE_G:
            case KeyEvent.KEYCODE_H:
            case KeyEvent.KEYCODE_I:
            case KeyEvent.KEYCODE_J:
            case KeyEvent.KEYCODE_K:
            case KeyEvent.KEYCODE_L:
            case KeyEvent.KEYCODE_M:
            case KeyEvent.KEYCODE_N:
            case KeyEvent.KEYCODE_O:
            case KeyEvent.KEYCODE_P:
            case KeyEvent.KEYCODE_Q:
            case KeyEvent.KEYCODE_R:
            case KeyEvent.KEYCODE_S:
            case KeyEvent.KEYCODE_T:
            case KeyEvent.KEYCODE_U:
            case KeyEvent.KEYCODE_V:
            case KeyEvent.KEYCODE_W:
            case KeyEvent.KEYCODE_X:
            case KeyEvent.KEYCODE_Y:
            case KeyEvent.KEYCODE_Z:
                char c = (char)(keyCode - KeyEvent.KEYCODE_A + 'A');
                if (hasMatches(mCityName + c)) {
                    mCityName += c;
                    shiftByName();
                }
                handled = true;
                break;

            // Remove a letter from the city name prefix
            case KeyEvent.KEYCODE_DEL:
                if (mCityName.length() > 0) {
                    mCityName = mCityName.substring(0, mCityName.length() - 1);
                    shiftByName();
                } else {
                    clearCityMatches();
                }
                handled = true;
                break;

            // Clear the city name prefix
            case KeyEvent.KEYCODE_ENTER:
                clearCityMatches();
                handled = true;
                break;
            }
        }

        boolean drawing = (mClockShowing ||
            ((mGLView != null) && (mGLView.hasMessages())));
        this.setWillNotDraw(!drawing);

        // Let the system handle other keypresses
        if (!handled) {
            return super.onKeyDown(keyCode, event);
        }
        return true;
    }

    /**
     * Initialize OpenGL ES drawing.
     */
    private synchronized void init(GL10 gl) {
        mGLView = new GLView();
        mGLView.setNearFrustum(5.0f);
        mGLView.setFarFrustum(50.0f);
        mGLView.setLightModelAmbientIntensity(0.225f);
        mGLView.setAmbientIntensity(0.0f);
        mGLView.setDiffuseIntensity(1.5f);
        mGLView.setDiffuseColor(SUNLIGHT_COLOR);
        mGLView.setSpecularIntensity(0.0f);
        mGLView.setSpecularColor(SUNLIGHT_COLOR);

        if (PERFORM_DEPTH_TEST) {
            gl.glEnable(GL10.GL_DEPTH_TEST);
        }
        gl.glDisable(GL10.GL_SCISSOR_TEST);
        gl.glClearColor(0, 0, 0, 1);
        gl.glHint(GL10.GL_POINT_SMOOTH_HINT, GL10.GL_NICEST);

        mInitialized = true;
    }

    /**
     * Computes the vector from the center of the earth to the sun for a
     * particular moment in time.
     */
    private void computeSunDirection() {
        mSunCal.setTimeInMillis(System.currentTimeMillis());
        int day = mSunCal.get(Calendar.DAY_OF_YEAR);
        int seconds = 3600 * mSunCal.get(Calendar.HOUR_OF_DAY) +
            60 * mSunCal.get(Calendar.MINUTE) + mSunCal.get(Calendar.SECOND);
        day += (float) seconds / SECONDS_PER_DAY;

        // Approximate declination of the sun, changes sinusoidally
        // during the year.  The winter solstice occurs 10 days before
        // the start of the year.
        float decl = (float) (EARTH_INCLINATION *
            Math.cos(Shape.TWO_PI * (day + 10) / 365.0));

        // Subsolar latitude, convert from (-PI/2, PI/2) -> (0, PI) form
        float phi = decl + Shape.PI_OVER_TWO;
        // Subsolar longitude
        float theta = Shape.TWO_PI * seconds / SECONDS_PER_DAY;

        float sinPhi = (float) Math.sin(phi);
        float cosPhi = (float) Math.cos(phi);
        float sinTheta = (float) Math.sin(theta);
        float cosTheta = (float) Math.cos(theta);

        // Convert from polar to rectangular coordinates
        float x = cosTheta * sinPhi;
        float y = cosPhi;
        float z = sinTheta * sinPhi;

        // Directional light -> w == 0
        mLightDir[0] = x;
        mLightDir[1] = y;
        mLightDir[2] = z;
        mLightDir[3] = 0.0f;
    }

    /**
     * Computes the approximate spherical distance between two
     * (latitude, longitude) coordinates.
     */
    private float distance(float lat1, float lon1,
                           float lat2, float lon2) {
        lat1 *= Shape.DEGREES_TO_RADIANS;
        lat2 *= Shape.DEGREES_TO_RADIANS;
        lon1 *= Shape.DEGREES_TO_RADIANS;
        lon2 *= Shape.DEGREES_TO_RADIANS;

        float r = 6371.0f; // Earth's radius in km
        float dlat = lat2 - lat1;
        float dlon = lon2 - lon1;
        double sinlat2 = Math.sin(dlat / 2.0f);
        sinlat2 *= sinlat2;
        double sinlon2 = Math.sin(dlon / 2.0f);
        sinlon2 *= sinlon2;

        double a = sinlat2 + Math.cos(lat1) * Math.cos(lat2) * sinlon2;
        double c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return (float) (r * c);
    }

    /**
     * Locates the closest city to the currently displayed center point,
     * optionally restricting the search to cities within a given time zone.
     */
    private void locateCity(boolean useOffset, float offset) {
        float mindist = Float.MAX_VALUE;
        int minidx = -1;
        for (int i = 0; i < mCities.size(); i++) {
            City city = mCities.get(i);
            if (useOffset && !tzEqual(getOffset(city), offset)) {
                continue;
            }
            float dist = distance(city.getLatitude(), city.getLongitude(),
                mTiltAngle, mRotAngle - 90.0f);
            if (dist < mindist) {
                mindist = dist;
                minidx = i;
            }
        }

        mCityIndex = minidx;
    }

    /**
     * Animates the earth to be centered at the current city.
     */
    private void goToCity() {
        City city = mCities.get(mCityIndex);
        float dist = distance(city.getLatitude(), city.getLongitude(),
            mTiltAngle, mRotAngle - 90.0f);

        mFlyToCity = true;
        mCityFlyStartTime = System.currentTimeMillis();
        mCityFlightTime = dist / 5.0f; // 5000 km/sec
        mRotAngleStart = mRotAngle;
        mRotAngleDest = city.getLongitude() + 90;

        if (mRotAngleDest - mRotAngleStart > 180.0f) {
            mRotAngleDest -= 360.0f;
        } else if (mRotAngleStart - mRotAngleDest > 180.0f) {
            mRotAngleDest += 360.0f;
        }

        mTiltAngleStart = mTiltAngle;
        mTiltAngleDest = city.getLatitude();
        mRotVelocity = 0.0f;
    }

    /**
     * Returns a linearly interpolated value between two values.
     */
    private float lerp(float a, float b, float lerp) {
        return a + (b - a)*lerp;
    }

    /**
     * Draws the city lights, using a clip plane to restrict the lights
     * to the night side of the earth.
     */
    private void drawCityLights(GL10 gl, float brightness) {
        gl.glEnable(GL10.GL_POINT_SMOOTH);
        gl.glDisable(GL10.GL_DEPTH_TEST);
        gl.glDisable(GL10.GL_LIGHTING);
        gl.glDisable(GL10.GL_DITHER);
        gl.glShadeModel(GL10.GL_FLAT);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        gl.glPointSize(1.0f);

        float ls = lerp(0.8f, 0.3f, brightness);
        gl.glColor4f(ls * 1.0f, ls * 1.0f, ls * 0.8f, 1.0f);

        if (mDisplayWorld) {
            mClipPlaneEquation[0] = -mLightDir[0];
            mClipPlaneEquation[1] = -mLightDir[1];
            mClipPlaneEquation[2] = -mLightDir[2];
            mClipPlaneEquation[3] = 0.0f;
            // Assume we have glClipPlanef() from OpenGL ES 1.1
            ((GL11) gl).glClipPlanef(GL11.GL_CLIP_PLANE0,
                mClipPlaneEquation, 0);
            gl.glEnable(GL11.GL_CLIP_PLANE0);
        }
        mLights.draw(gl);
        if (mDisplayWorld) {
            gl.glDisable(GL11.GL_CLIP_PLANE0);
        }

        mNumTriangles += mLights.getNumTriangles()*2;
    }

    /**
     * Draws the atmosphere.
     */
    private void drawAtmosphere(GL10 gl) {
        gl.glDisable(GL10.GL_LIGHTING);
        gl.glDisable(GL10.GL_CULL_FACE);
        gl.glDisable(GL10.GL_DITHER);
        gl.glDisable(GL10.GL_DEPTH_TEST);
        gl.glShadeModel(mSmoothShading ? GL10.GL_SMOOTH : GL10.GL_FLAT);

        // Draw the atmospheric layer
        float tx = mGLView.getTranslateX();
        float ty = mGLView.getTranslateY();
        float tz = mGLView.getTranslateZ();

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(tx, ty, tz);

        // Blend in the atmosphere a bit
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        ATMOSPHERE.draw(gl);

        mNumTriangles += ATMOSPHERE.getNumTriangles();
    }

    /**
     * Draws the world in a 2D map view.
     */
    private void drawWorldFlat(GL10 gl) {
        gl.glDisable(GL10.GL_BLEND);
        gl.glEnable(GL10.GL_DITHER);
        gl.glShadeModel(mSmoothShading ? GL10.GL_SMOOTH : GL10.GL_FLAT);

        gl.glTranslatef(mWrapX - 2, 0.0f, 0.0f);
        worldFlat.draw(gl);
        gl.glTranslatef(2.0f, 0.0f, 0.0f);
        worldFlat.draw(gl);
        mNumTriangles += worldFlat.getNumTriangles() * 2;

        mWrapX += mWrapVelocity * mWrapVelocityFactor;
        while (mWrapX < 0.0f) {
            mWrapX += 2.0f;
        }
        while (mWrapX > 2.0f) {
            mWrapX -= 2.0f;
        }
    }

    /**
     * Draws the world in a 2D round view.
     */
    private void drawWorldRound(GL10 gl) {
        gl.glDisable(GL10.GL_BLEND);
        gl.glEnable(GL10.GL_DITHER);
        gl.glShadeModel(mSmoothShading ? GL10.GL_SMOOTH : GL10.GL_FLAT);

        mWorld.draw(gl);
        mNumTriangles += mWorld.getNumTriangles();
    }

    /**
     * Draws the clock.
     *
     * @param canvas the Canvas to draw to
     * @param now the current time
     * @param w the width of the screen
     * @param h the height of the screen
     * @param lerp controls the animation, between 0.0 and 1.0
     */
    private void drawClock(Canvas canvas,
                           long now,
                           int w, int h,
                           float lerp) {
        float clockAlpha = lerp(0.0f, 0.8f, lerp);
        mClockShowing = clockAlpha > 0.0f;
        if (clockAlpha > 0.0f) {
            City city = mCities.get(mCityIndex);
            mClock.setCity(city);
            mClock.setTime(now);

            float cx = w / 2.0f;
            float cy = h / 2.0f;
            float smallRadius = 18.0f;
            float bigRadius = 0.75f * 0.5f * Math.min(w, h);
            float radius = lerp(smallRadius, bigRadius, lerp);

            // Only display left/right arrows if we are in a name search
            boolean scrollingByName =
                (mCityName.length() > 0) && (mCities.size() > 1);
            mClock.drawClock(canvas, cx, cy, radius,
                             clockAlpha,
                             1.0f,
                             lerp == 1.0f, lerp == 1.0f,
                             !atEndOfTimeZone(-1),
                             !atEndOfTimeZone(1),
                             scrollingByName,
                             mCityName.length());
        }
    }

    /**
     * Draws the 2D layer.
     */
    @Override protected void onDraw(Canvas canvas) {
        long now = System.currentTimeMillis();
        if (startTime != -1) {
            startTime = -1;
        }

        int w = getWidth();
        int h = getHeight();

        // Interpolator for clock size, clock alpha, night lights intensity
        float lerp = Math.min((now - mClockFadeTime)/1000.0f, 1.0f);
        if (!mDisplayClock) {
            // Clock is receding
            lerp = 1.0f - lerp;
        }
        lerp = mClockSizeInterpolator.getInterpolation(lerp);

        // we don't need to make sure OpenGL rendering is done because
        // we're drawing in to a different surface

        drawClock(canvas, now, w, h, lerp);

        mGLView.showMessages(canvas);
        mGLView.showStatistics(canvas, w);
    }

    /**
     * Draws the 3D layer.
     */
    protected void drawOpenGLScene() {
        long now = System.currentTimeMillis();
        mNumTriangles = 0;

        EGL10 egl = (EGL10)EGLContext.getEGL();
        GL10 gl = (GL10)mEGLContext.getGL();

        if (!mInitialized) {
            init(gl);
        }

        int w = getWidth();
        int h = getHeight();
        gl.glViewport(0, 0, w, h);

        gl.glEnable(GL10.GL_LIGHTING);
        gl.glEnable(GL10.GL_LIGHT0);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glFrontFace(GL10.GL_CCW);

        float ratio = (float) w / h;
        mGLView.setAspectRatio(ratio);

        mGLView.setTextureParameters(gl);

        if (PERFORM_DEPTH_TEST) {
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        } else {
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        }

        if (mDisplayWorldFlat) {
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            gl.glFrustumf(-1.0f, 1.0f, -1.0f / ratio, 1.0f / ratio, 1.0f, 2.0f);
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
            gl.glTranslatef(0.0f, 0.0f, -1.0f);
        } else {
            mGLView.setProjection(gl);
            mGLView.setView(gl);
        }

        if (!mDisplayWorldFlat) {
            if (mFlyToCity) {
                float lerp = (now - mCityFlyStartTime)/mCityFlightTime;
                if (lerp >= 1.0f) {
                    mFlyToCity = false;
                }
                lerp = Math.min(lerp, 1.0f);
                lerp = mFlyToCityInterpolator.getInterpolation(lerp);
                mRotAngle = lerp(mRotAngleStart, mRotAngleDest, lerp);
                mTiltAngle = lerp(mTiltAngleStart, mTiltAngleDest, lerp);
            }

            // Rotate the viewpoint around the earth
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glRotatef(mTiltAngle, 1, 0, 0);
            gl.glRotatef(mRotAngle, 0, 1, 0);

            // Increment the rotation angle
            mRotAngle += mRotVelocity;
            if (mRotAngle < 0.0f) {
                mRotAngle += 360.0f;
            }
            if (mRotAngle > 360.0f) {
                mRotAngle -= 360.0f;
            }
        }

        // Draw the world with lighting
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, mLightDir, 0);
        mGLView.setLights(gl, GL10.GL_LIGHT0);

        if (mDisplayWorldFlat) {
            drawWorldFlat(gl);
        } else if (mDisplayWorld) {
            drawWorldRound(gl);
        }

        if (mDisplayLights && !mDisplayWorldFlat) {
            // Interpolator for clock size, clock alpha, night lights intensity
            float lerp = Math.min((now - mClockFadeTime)/1000.0f, 1.0f);
            if (!mDisplayClock) {
                // Clock is receding
                lerp = 1.0f - lerp;
            }
            lerp = mClockSizeInterpolator.getInterpolation(lerp);
            drawCityLights(gl, lerp);
        }

        if (mDisplayAtmosphere && !mDisplayWorldFlat) {
            drawAtmosphere(gl);
        }
        mGLView.setNumTriangles(mNumTriangles);
        egl.eglSwapBuffers(mEGLDisplay, mEGLSurface);

        if (egl.eglGetError() == EGL11.EGL_CONTEXT_LOST) {
            // we lost the gpu, quit immediately
            Context c = getContext();
            if (c instanceof Activity) {
                ((Activity)c).finish();
            }
        }
    }


    private static final int INVALIDATE = 1;
    private static final int ONE_MINUTE = 60000;

    /**
     * Controls the animation using the message queue.  Every time we receive
     * an INVALIDATE message, we redraw and place another message in the queue.
     */
    private final Handler mHandler = new Handler() {
        private long mLastSunPositionTime = 0;

        @Override public void handleMessage(Message msg) {
            if (msg.what == INVALIDATE) {

                // Use the message's time, it's good enough and
                // allows us to avoid a system call.
                if ((msg.getWhen() - mLastSunPositionTime) >= ONE_MINUTE) {
                    // Recompute the sun's position once per minute
                    // Place the light at the Sun's direction
                    computeSunDirection();
                    mLastSunPositionTime = msg.getWhen();
                }

                // Draw the GL scene
                drawOpenGLScene();

                // Send an update for the 2D overlay if needed
                if (mInitialized &&
                                (mClockShowing || mGLView.hasMessages())) {
                    invalidate();
                }

                // Just send another message immediately. This works because
                // drawOpenGLScene() does the timing for us -- it will
                // block until the last frame has been processed.
                // The invalidate message we're posting here will be
                // interleaved properly with motion/key events which
                // guarantee a prompt reaction to the user input.
                sendEmptyMessage(INVALIDATE);
            }
        }
    };
}

/**
 * The main activity class for GlobalTime.
 */
public class GlobalTime extends Activity {

    GTView gtView = null;

    @Override protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        gtView = new GTView(this);
        setContentView(gtView);
    }

    @Override protected void onResume() {
        super.onResume();
        gtView.onResume();
        Looper.myQueue().addIdleHandler(new Idler());
    }

    @Override protected void onPause() {
        super.onPause();
        gtView.onPause();
    }

    @Override protected void onStop() {
        super.onStop();
        gtView.destroy();
        gtView = null;
    }

    // Allow the activity to go idle before its animation starts
    class Idler implements MessageQueue.IdleHandler {
        public Idler() {
            super();
        }

        public final boolean queueIdle() {
            if (gtView != null) {
                gtView.startAnimating();
            }
            return false;
        }
    }
}
