/*
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
 *
 *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
 *  Adrien Béraud <adrien.beraud@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
 */

package org.sflphone.model;

import java.util.List;

import org.sflphone.R;
import org.sflphone.fragments.CallFragment;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;

public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
    private static final String TAG = BubblesView.class.getSimpleName();

    private BubblesThread thread = null;
    private BubbleModel model;

    private Paint black_name_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint white_name_paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private GestureDetector gDetector;

    private float density;
    private float textDensity;

    private boolean dragging_bubble = false;

    private CallFragment callback;

    public BubblesView(Context context, AttributeSet attrs) {
        super(context, attrs);

        density = getResources().getDisplayMetrics().density;
        textDensity = getResources().getDisplayMetrics().scaledDensity;

        SurfaceHolder holder = getHolder();
        holder.addCallback(this);

        this.setZOrderOnTop(true); // necessary
        this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        // create thread only; it's started in surfaceCreated()
        createThread();

        setOnTouchListener(this);
        setFocusable(true);

        black_name_paint.setTextSize(18 * textDensity);
        black_name_paint.setColor(0xFF303030);
        black_name_paint.setTextAlign(Align.CENTER);

        white_name_paint.setTextSize(18 * textDensity);
        white_name_paint.setColor(0xFFEEEEEE);
        white_name_paint.setTextAlign(Align.CENTER);

        gDetector = new GestureDetector(getContext(), new MyOnGestureListener());
    }

    private void createThread() {
        if (thread != null)
            return;
        thread = new BubblesThread(getHolder(), getContext());
        if (model != null)
            thread.setModel(model);
    }

    public void setModel(BubbleModel model) {
        this.model = model;
        thread.setModel(model);
    }

    /*
     * @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (!hasWindowFocus) { thread.pause(); } }
     */

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.w(TAG, "surfaceChanged " + width + "-" + height);
        if (height < model.height) // probably showing the keyboard, don't move!
            return;

        thread.setSurfaceSize(width, height);
    }

    /*
     * Callback invoked when the Surface has been created and is ready to be used.
     */
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // start the thread here so that we don't busy-wait in run()
        // waiting for the surface to be created
        createThread();

        Log.w(TAG, "surfaceCreated");
        thread.setRunning(true);
        thread.start();
    }

    /*
     * Callback invoked when the Surface has been destroyed and must no longer be touched. WARNING: after this method returns, the Surface/Canvas must
     * never be touched again!
     */
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // we have to tell thread to shut down & wait for it to finish, or else
        // it might touch the Surface after we return and explode
        Log.w(TAG, "surfaceDestroyed");
        boolean retry = true;
        thread.setRunning(false);
        thread.setPaused(false);
        while (retry) {
            try {
                Log.w(TAG, "joining...");
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
        Log.w(TAG, "done");
        thread = null;
    }

    public boolean isDraggingBubble() {
        return dragging_bubble;
    }

    class BubblesThread extends Thread {
        private boolean running = false;
        private SurfaceHolder surfaceHolder;
        public Boolean suspendFlag = false;

        BubbleModel model = null;

        public BubblesThread(SurfaceHolder holder, Context context) {
            surfaceHolder = holder;
        }

        public void setModel(BubbleModel model) {
            this.model = model;
        }

        @Override
        public void run() {
            while (running) {
                Canvas c = null;
                try {

                    if (suspendFlag) {
                        synchronized (this) {
                            while (suspendFlag) {
                                try {
                                    wait();
                                } catch (InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                        }
                    } else {
                        c = surfaceHolder.lockCanvas(null);

                        // for the case the surface is destroyed while already in the loop
                        if (c == null || model == null)
                            continue;

                        synchronized (surfaceHolder) {
                            // Log.w(TAG, "Thread doDraw");
                            model.update();
                            doDraw(c);
                        }
                    }

                } finally {
                    if (c != null)
                        surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }

        public void setPaused(boolean wantToPause) {
            synchronized (this) {
                suspendFlag = wantToPause;
                notify();
            }
        }

        public void setRunning(boolean b) {
            running = b;
        }

        public void setSurfaceSize(int width, int height) {
            synchronized (surfaceHolder) {
                if (model != null) {
                    model.width = width;
                    model.height = height;
                }
            }
        }

        /**
         * got multiple IndexOutOfBoundsException, when switching calls. //FIXME
         * 
         * @param canvas
         */
        private void doDraw(Canvas canvas) {

            synchronized (model) {
                List<Bubble> bubbles = model.getBubbles();
                List<Attractor> attractors = model.getAttractors();

                Paint tryMe = new Paint();

                Paint paint = new Paint();
                paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
                canvas.drawPaint(paint);
                paint.setXfermode(new PorterDuffXfermode(Mode.SRC));

                // canvas.drawColor(Color.LTGRAY);

                if (dragging_bubble) {
                    Paint p = new Paint();
                    p.setDither(true);
                    p.setColor(getResources().getColor(R.color.holo_red_light));
                    p.setStyle(Style.STROKE);
                    p.setStrokeWidth(20);
                    canvas.drawRect(new RectF(10, 10, model.width - 10, model.height - 10), p);
                }

                tryMe.setStyle(Paint.Style.STROKE);
                tryMe.setColor(getResources().getColor(R.color.darker_gray));
                tryMe.setXfermode(null);
                canvas.drawCircle(model.width / 2, model.height / 2, model.width / 2 - getResources().getDimension(R.dimen.bubble_size), tryMe);

                try {

                    for (int i = 0, n = attractors.size(); i < n; i++) {
                        Attractor a = attractors.get(i);
                        canvas.drawBitmap(a.getBitmap(), null, a.getBounds(), null);
                    }

                    for (int i = 0, n = bubbles.size(); i < n; i++) {
                        Bubble b = bubbles.get(i);
                        if (b.expanded) {
                            continue;
                        }
                        canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);
                        canvas.drawText(b.getName(), b.getPosX(), (float) (b.getPosY() - b.getRetractedRadius() * 1.2 * density), getNamePaint(b));
                    }

                    Bubble first_plan = getExpandedBubble();
                    if (first_plan != null) {

                        if (first_plan.getDrawerBitmap() != null) {
                            canvas.drawBitmap(first_plan.getDrawerBitmap(), null, first_plan.getDrawerBounds(), null);
                        }
                        canvas.drawBitmap(first_plan.getBitmap(), null, first_plan.getBounds(), null);
                        // canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(),
                        // (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.2 * density), getNamePaint(first_plan));

                    }

                } catch (IndexOutOfBoundsException e) {
                    Log.e(TAG, e.toString());
                }
            }
        }

    }

    private Paint getNamePaint(Bubble b) {
        if (b.expanded) {
            white_name_paint.setTextSize(15 * b.target_scale * textDensity);
            return white_name_paint;
        }
        black_name_paint.setTextSize(18 * b.target_scale * textDensity);
        return black_name_paint;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // Log.w(TAG, "onTouch " + event.getAction());

        int action = event.getActionMasked();

        if (gDetector.onTouchEvent(event))
            return true;

        if (action == MotionEvent.ACTION_UP) {
            if (thread.suspendFlag) {
                Log.i(TAG, "Relaunch drawing thread");
                thread.setPaused(false);
            }

            Bubble expand = getExpandedBubble();
            if (expand != null) {
                switch (expand.getDrawer().getAction(event.getX(), event.getY())) {
                case Bubble.actions.OUT_OF_BOUNDS:
                    expand.retract();
                    break;
                case Bubble.actions.HOLD:

                    try {
                        if (expand.getHoldStatus()) {

                            if (expand.isConference())
                                callback.mCallbacks.getService().unholdConference(expand.getCallID());
                            else
                                callback.mCallbacks.getService().unhold(expand.getCallID());
                        } else {
                            if (expand.isConference())
                                callback.mCallbacks.getService().holdConference(expand.getCallID());
                            else
                                callback.mCallbacks.getService().hold(expand.getCallID());

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    return true;
                case Bubble.actions.RECORD:
                    try {
                        boolean isRecording = callback.mCallbacks.getService().toggleRecordingCall(expand.getCallID());
                        ((BubbleUser) expand).associated_call.setRecording(isRecording);
                    } catch (RemoteException e1) {
                        e1.printStackTrace();
                    }
                    return true;
                case Bubble.actions.MESSAGE:
                    // TODO
                    return true;
                case Bubble.actions.MUTE:
                    try {
                        callback.mCallbacks.getService().setMuted(!((BubbleUser) expand).getMute());
                        ((BubbleUser) expand).toggleMute();
                    } catch (RemoteException e1) {
                        e1.printStackTrace();
                    }
                    return true;
                case Bubble.actions.HANGUP:
                    try {
                        if (expand.isConference())
                            callback.mCallbacks.getService().hangUpConference(expand.getCallID());
                        else
                            callback.mCallbacks.getService().hangUp(expand.getCallID());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    return true;

                case Bubble.actions.TRANSFER:
                    callback.makeTransfer((BubbleContact) expand);
                    return true;
                case Bubble.actions.NOTHING:
                    break;
                }

            }

            List<Bubble> bubbles = model.getBubbles();
            final int n_bubbles = bubbles.size();
            for (int i = 0; i < n_bubbles; i++) {
                Bubble b = bubbles.get(i);
                if (b.dragged) {
                    b.dragged = false;
                    b.target_scale = 1.f;
                    if (b.isOnBorder(model.width, model.height) && !b.expanded) {
                        b.markedToDie = true;

                        try {
                            if (b.isConference())
                                callback.mCallbacks.getService().hangUpConference(b.getCallID());
                            else
                                callback.mCallbacks.getService().hangUp(b.getCallID());

                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            dragging_bubble = false;
        } else if (action != MotionEvent.ACTION_DOWN && !isDraggingBubble() && !thread.suspendFlag) {

            Log.i(TAG, "Not dragging thread should be stopped");
            thread.setPaused(true);
            // thread.holdDrawing();
        }

        return true;
    }

    private Bubble getExpandedBubble() {
        List<Bubble> bubbles = model.getBubbles();
        final int n_bubbles = bubbles.size();
        for (int i = 0; i < n_bubbles; i++) {
            Bubble b = bubbles.get(i);
            if (b.expanded) {
                return b;
            }
        }
        return null;
    }

    public void restartDrawing() {
        if (thread != null && thread.suspendFlag) {
            Log.i(TAG, "Relaunch drawing thread");
            thread.setPaused(false);
        }
    }

    public void setFragment(CallFragment callFragment) {
        callback = callFragment;

    }

    public void stopThread() {
        if (thread != null && thread.suspendFlag) {
            Log.i(TAG, "Stop drawing thread");
            thread.setPaused(true);
        }

    }

    class MyOnGestureListener implements OnGestureListener {
        @Override
        public boolean onDown(MotionEvent event) {
            List<Bubble> bubbles = model.getBubbles();

            Bubble target = getExpandedBubble();
            if (target != null) {
                target.onDown(event);
                return true;
            }

            for (int i = 0; i < bubbles.size(); i++) {
                Bubble b = bubbles.get(i);
                if (b.onDown(event))
                    dragging_bubble = true;
            }

            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            // Log.d("Main", "onFling");
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            // Log.d("Main", "onLongPress");

        }

        private Bubble getDraggedBubble(MotionEvent e) {
            List<Bubble> bubbles = model.getBubbles();
            final int n_bubbles = bubbles.size();
            for (int i = 0; i < n_bubbles; i++) {
                Bubble b = bubbles.get(i);
                if (b.intersects(e.getX(), e.getY())) {
                    return b;
                }
            }
            return null;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent event, float distanceX, float distanceY) {
            // Log.d("Main", "onScroll");
            List<Bubble> bubbles = model.getBubbles();

            long now = System.nanoTime();
            for (int i = 0; i < bubbles.size(); i++) {
                Bubble b = bubbles.get(i);
                if (b.dragged) {
                    float x = event.getX(), y = event.getY();
                    float dt = (float) ((now - b.last_drag) / 1000000000.);
                    float dx = x - b.getPosX(), dy = y - b.getPosY();
                    b.last_drag = now;
                    b.setPos(event.getX(), event.getY());
                    b.speed.x = dx / dt;
                    b.speed.y = dy / dt;

                    return false;
                }
            }
            return true;
        }

        @Override
        public void onShowPress(MotionEvent e) {
            // Log.d("Main", "onShowPress");

        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            if (isDraggingBubble() && callback.getConference().isOnGoing()) {
                Bubble b = getDraggedBubble(e);
                b.expand(model.width, model.height);
                dragging_bubble = false;
            }
            return false;

        }
    }
}
