package org.supertuxkart.stk_dbg;

import org.supertuxkart.stk_dbg.STKEditText;
import org.libsdl.app.SDLActivity;
import org.libsdl.app.SDL;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Process;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.inputmethod.InputMethodManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.util.DisplayMetrics;

import java.io.InputStream;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Set;

import org.minidns.hla.DnssecResolverApi;
import org.minidns.hla.ResolverResult;
import org.minidns.record.SRV;
import org.minidns.record.TXT;

public class SuperTuxKartActivity extends SDLActivity
{
    private AlertDialog m_progress_dialog;
    private ProgressBar m_progress_bar;
    private ImageView m_splash_screen;
    private STKEditText m_stk_edittext;
    private int m_bottom_y;
    private int m_intial_orientation;
    private float m_top_padding;
    private float m_bottom_padding;
    private float m_left_padding;
    private float m_right_padding;
    private AtomicInteger m_keyboard_height;
    private AtomicInteger m_moved_height;
    // ------------------------------------------------------------------------
    public native static void debugMsg(String msg);
    // ------------------------------------------------------------------------
    private native static void handlePadding(boolean val);
    // ------------------------------------------------------------------------
    private native static void saveKeyboardHeight(int height);
    // ------------------------------------------------------------------------
    private native static void saveMovedHeight(int height);
    // ------------------------------------------------------------------------
    private native static void addDNSSrvRecords(String name, int weight);
    // ------------------------------------------------------------------------
    private native static void pauseRenderingJNI();
    // ------------------------------------------------------------------------
    private void showExtractProgressPrivate()
    {
        WindowManager wm =
            (WindowManager)getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics display_metrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(display_metrics);
        int padding = display_metrics.widthPixels / 64;

        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.VERTICAL);
        ll.setPadding(padding, padding, padding, padding);
        ll.setGravity(Gravity.CENTER);

        LinearLayout.LayoutParams ll_param = new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
        ll_param.gravity = Gravity.CENTER;
        TextView tv = new TextView(this);
        // From values strings.xml which is generated by make.sh
        tv.setText(getString(R.string.po_extract_game_data));
        tv.setLayoutParams(ll_param);

        ll_param = new LinearLayout.LayoutParams(
            display_metrics.widthPixels,
            LinearLayout.LayoutParams.WRAP_CONTENT);
        ll_param.gravity = Gravity.CENTER;
        ll.setLayoutParams(ll_param);

        m_progress_bar = new ProgressBar(this, null,
            android.R.attr.progressBarStyleHorizontal);
        m_progress_bar.setIndeterminate(false);
        m_progress_bar.setPadding(0, padding, 0, padding);
        m_progress_bar.setLayoutParams(ll_param);
        ll.addView(tv);
        ll.addView(m_progress_bar);

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setCancelable(false);
        builder.setView(ll);

        m_progress_dialog = builder.create();
        m_progress_dialog.show();
        Window window = m_progress_dialog.getWindow();
        if (window != null)
        {
            WindowManager.LayoutParams layout_params =
                new WindowManager.LayoutParams();
            layout_params.copyFrom(
                m_progress_dialog.getWindow().getAttributes());
            layout_params.width = WindowManager.LayoutParams.MATCH_PARENT;
            layout_params.height = LinearLayout.LayoutParams.WRAP_CONTENT;
            m_progress_dialog.getWindow().setAttributes(layout_params);
        }
    }
    // ------------------------------------------------------------------------
    private void hideKeyboardNative(final boolean clear_text)
    {
        if (m_stk_edittext == null)
            return;

        m_stk_edittext.beforeHideKeyboard(clear_text);

        InputMethodManager imm = (InputMethodManager)
            getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm == null)
            return;

        imm.hideSoftInputFromWindow(m_stk_edittext.getWindowToken(), 0);
    }
    // ------------------------------------------------------------------------
    private void createSTKEditText()
    {
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.WRAP_CONTENT,
            FrameLayout.LayoutParams.WRAP_CONTENT);
        // We move the dummy edittext out of the android screen because we draw
        // our own manually
        params.setMargins(0, -100000, 1, -100010);
        m_stk_edittext = new STKEditText(this);
        // For some copy-and-paste text are not done by commitText in
        // STKInputConnection, so we need an extra watcher
        m_stk_edittext.addTextChangedListener(new TextWatcher()
        {
            @Override
            public void onTextChanged(CharSequence s, int start, int before,
                                      int count) {}
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                                          int after) {}
            @Override
            public void afterTextChanged(Editable edit)
            {
                if (m_stk_edittext != null)
                    m_stk_edittext.updateSTKEditBox();
            }
        });
        addContentView(m_stk_edittext, params);
        // Only focus it and make visible when soft keybord is opened
        m_stk_edittext.setVisibility(View.GONE);
    }
    // ------------------------------------------------------------------------
    @Override
    public void onCreate(Bundle instance)
    {
        super.onCreate(instance);
        m_keyboard_height = new AtomicInteger();
        m_moved_height = new AtomicInteger();
        m_progress_dialog = null;
        m_progress_bar = null;
        m_splash_screen = null;
        m_bottom_y = m_intial_orientation = 0;
        m_top_padding = m_bottom_padding = m_left_padding = m_right_padding =
            0.0f;
        final View root = getWindow().getDecorView().findViewById(
            android.R.id.content);
        root.getViewTreeObserver().addOnGlobalLayoutListener(new
            OnGlobalLayoutListener()
            {
                @Override
                public void onGlobalLayout()
                {
                    Rect r = new Rect();
                    root.getWindowVisibleDisplayFrame(r);
                    int screen_height = root.getRootView().getHeight();
                    int keyboard_height = screen_height - (r.bottom);
                    m_keyboard_height.set(keyboard_height);
                    int moved_height = 0;
                    int margin = screen_height - m_bottom_y;
                    if (keyboard_height > margin)
                        moved_height = -keyboard_height + margin;
                    m_moved_height.set(-moved_height);
                    SDLActivity.moveView(moved_height);
                }
            });

        InputStream istr = null;
        try
        {
            LinearLayout ll = new LinearLayout(this);
            LinearLayout.LayoutParams ll_param = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
            ll.setLayoutParams(ll_param);

            WindowManager wm =
                (WindowManager)getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics display_metrics = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(display_metrics);
            Bitmap.Config conf = Bitmap.Config.ARGB_8888;
            int w = display_metrics.widthPixels;
            int h = display_metrics.heightPixels;
            Bitmap scaled = Bitmap.createBitmap(w, h, conf);

            Canvas canvas = new Canvas(scaled);
            istr = getAssets().open("data/gui/icons/logo.png");
            Bitmap logo = BitmapFactory.decodeStream(istr);
            Rect src = new Rect(0, 0, logo.getWidth(), logo.getHeight());
            // STK logo is a square
            int target_size = w;
            if (target_size > h)
                target_size = h;
            target_size /= 2;
            Rect dest = new Rect(w / 2 - target_size / 2,
                h / 2 - target_size / 2,
                w / 2 - target_size / 2 + target_size,
                h / 2 - target_size / 2 + target_size);
            canvas.drawBitmap(logo, src, dest, null);

            m_splash_screen = new ImageView(this);
            m_splash_screen.setBackgroundColor(Color.argb(255, 168, 168, 168));
            m_splash_screen.setImageDrawable(new BitmapDrawable(getResources(),
                scaled));
            addContentView(m_splash_screen, ll_param);
        }
        catch (Exception e) {}
        finally
        {
            try
            {
                if (istr != null)
                    istr.close();
            }
            catch(Exception e) {}
        }
    }
    // ------------------------------------------------------------------------
    @Override
    public void onStart()
    {
        super.onStart();
        m_keyboard_height.set(0);
        m_moved_height.set(0);
    }
    // ------------------------------------------------------------------------
    @Override
    public void onPause()
    {
        super.onPause();
        hideKeyboardNative(false/*clear_text*/);
        if (SDLActivity.mSDLThread != null)
            pauseRenderingJNI();
    }
    // ------------------------------------------------------------------------
    /* SDL manually dlopen main to allow unload after main thread exit. */
    protected String[] getLibraries()
    {
        return new String[]{ "SDL2" };
    }
    // ------------------------------------------------------------------------
    protected String getMainSharedObject()
    {
        return getContext().getApplicationInfo().nativeLibraryDir + "/libmain.so";
    }
    // ------------------------------------------------------------------------
    public void showKeyboard(final int type, final int y)
    {
        final Context context = this;
        // Need to run in ui thread as it access the view m_stk_edittext
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                m_bottom_y = y;
                InputMethodManager imm = (InputMethodManager)
                    getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm == null)
                    return;

                if (m_stk_edittext == null)
                    createSTKEditText();

                m_stk_edittext.configType(type);
                m_stk_edittext.setVisibility(View.VISIBLE);
                m_stk_edittext.requestFocus();

                imm.showSoftInput(m_stk_edittext,
                    InputMethodManager.SHOW_FORCED);
            }
        });
    }
    // ------------------------------------------------------------------------
    /* Called by STK in JNI. */
    public void hideKeyboard(final boolean clear_text)
    {
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                m_bottom_y = 0;
                hideKeyboardNative(clear_text);
            }
        });
    }
    // ------------------------------------------------------------------------
    /* Called by STK in JNI. */
    public void fromSTKEditBox(final int widget_id, final String text,
                               final int selection_start,
                               final int selection_end, final int type)
    {
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                if (m_stk_edittext == null)
                    createSTKEditText();
                m_stk_edittext.configType(type);
                m_stk_edittext.setTextFromSTK(widget_id, text, selection_start,
                    selection_end);
            }
        });
    }
    // ------------------------------------------------------------------------
    public String[] getDNSTxtRecords(String domain)
    {
        try
        {
            ResolverResult<TXT> txts =
                DnssecResolverApi.INSTANCE.resolve(domain, TXT.class);
            Set<TXT> ans = txts.getAnswers();
            String[] result = new String[ans.size()];
            int i = 0;
            for (TXT t : ans)
                result[i++] = t.getText();
            return result;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return new String[0];
        }
    }
    // ------------------------------------------------------------------------
    public void getDNSSrvRecords(String domain)
    {
        try
        {
            ResolverResult<SRV> srvs =
                DnssecResolverApi.INSTANCE.resolve(domain, SRV.class);
            Set<SRV> ans = srvs.getAnswers();
            for (SRV s : ans)
                addDNSSrvRecords(s.target.toString() + ":" + s.port, s.weight);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    // ------------------------------------------------------------------------
    public boolean isHardwareKeyboardConnected()
    {
        return getResources().getConfiguration()
            .keyboard == Configuration.KEYBOARD_QWERTY;
    }
    // ------------------------------------------------------------------------
    public int getScreenSize()
    {
        return getResources().getConfiguration().screenLayout &
            Configuration.SCREENLAYOUT_SIZE_MASK;
    }
    // ------------------------------------------------------------------------
    public float getTopPadding()                      { return m_top_padding; }
    // ------------------------------------------------------------------------
    public float getBottomPadding()                { return m_bottom_padding; }
    // ------------------------------------------------------------------------
    public float getLeftPadding()                    { return m_left_padding; }
    // ------------------------------------------------------------------------
    public float getRightPadding()                  { return m_right_padding; }
    // ------------------------------------------------------------------------
    public int getInitialOrientation()         { return m_intial_orientation; }
    // ------------------------------------------------------------------------

    public void showExtractProgress(final int progress)
    {
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                if (progress == -1)
                {
                    if (m_progress_dialog != null)
                    {
                        m_progress_dialog.dismiss();
                        m_progress_dialog = null;
                        m_progress_bar = null;
                    }
                    AlertDialog.Builder error =
                        new AlertDialog.Builder(SDL.getContext());
                    error.setMessage(getString(R.string.po_extract_error_msg));
                    error.setTitle(getString(R.string.po_extract_error));
                    error.setPositiveButton(getString(R.string.po_quit),
                        new DialogInterface.OnClickListener()
                        {
                            @Override
                            public void onClick(DialogInterface dialog,
                                                int id)
                            {
                                android.os.Process.killProcess(
                                    android.os.Process.myPid());
                            }
                        });
                    error.setCancelable(false);
                    error.create().show();
                    return;
                }
                if (progress == 0 && m_progress_dialog == null)
                    showExtractProgressPrivate();
                else if (progress == 100 && m_progress_dialog != null)
                {
                    m_progress_dialog.dismiss();
                    m_progress_dialog = null;
                    m_progress_bar = null;
                }
                else if (m_progress_bar != null &&
                    m_progress_bar.getProgress() != progress)
                {
                    m_progress_bar.setProgress(progress);
                }
            }
        });

    }
    // ------------------------------------------------------------------------
    public void hideSplashScreen()
    {
        if (m_splash_screen != null)
        {
            m_splash_screen.animate().setDuration(200).alpha(0).setListener(
            new AnimatorListenerAdapter()
            {
                @Override
                public void onAnimationEnd(Animator animation)
                {
                    if (m_splash_screen.getParent() instanceof ViewGroup)
                    {
                        ViewGroup view = (ViewGroup)m_splash_screen.getParent();
                        view.removeView(m_splash_screen);
                        m_splash_screen = null;
                    }
                }
            });
        }
    }
    // ------------------------------------------------------------------------
    @Override
    public void onAttachedToWindow()
    {
        super.onAttachedToWindow();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
        {
            DisplayCutout dc = getWindow().getDecorView().getRootWindowInsets()
                .getDisplayCutout();
            if (dc != null)
            {
                m_top_padding = (float)dc.getBoundingRectTop().height();
                m_bottom_padding = (float)dc.getBoundingRectBottom().height();
                m_left_padding = (float)dc.getBoundingRectLeft().width();
                m_right_padding = (float)dc.getBoundingRectRight().width();
                // Left or right will depend on the device initial orientation
                // So save it for dealing with device rotation later
                m_intial_orientation = SDLActivity.getCurrentOrientation();
            }
        }
    }
    // ------------------------------------------------------------------------
    @Override
    public void onMultiWindowModeChanged(boolean isInMultiWindowMode,
                                         Configuration newConfig)
    {
        handlePadding(isInMultiWindowMode);
    }
    // ------------------------------------------------------------------------
    public int getKeyboardHeight()          { return m_keyboard_height.get(); }
    // ------------------------------------------------------------------------
    public int getMovedHeight()                { return m_moved_height.get(); }
    // ------------------------------------------------------------------------
    public String getLocaleString()
    {
        String language = "";
        if (mCurrentLocale != null)
        {
            language = mCurrentLocale.getLanguage();
            if (language == "iw")
                language = "he";
            else if (language == "in")
                language = "id";
            else if (language == "ji")
                language = "yi";
            String country = mCurrentLocale.getCountry();
            if (country != "")
                language += "_" + country;
        }
        return language;
    }

}
