package jp.sourceforge.nicoro;

import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.test.AndroidTestCase;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.ToggleButton;

import jp.gr.java_conf.shiseissi.commonlib.ViewUtil;

public class PlayerControllerViewsTest extends AndroidTestCase {
    private LayoutInflater mInflater;
    private View mRootView;
    private Resources mRes;
    private PlayerControllerViews mViews;

    @Override
    protected void setUp() {
        mInflater = LayoutInflater.from(getContext());
        assertNotNull(mInflater);
        mRootView = createRootView(mInflater);
        assertNotNull(mRootView);
        mRes = getContext().getResources();
        mViews = new PlayerControllerViews();
        mViews.initializeView(mRootView);
    }

    @Override
    protected void tearDown() {
        mInflater = null;
        mRootView = null;
        mRes = null;
        mViews = null;
    }

    public void testCopyLayoutParamsFrom() {
        Configuration configOrg = mRes.getConfiguration();
        try {
            Configuration config = new Configuration(configOrg);
            if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
                config.orientation = Configuration.ORIENTATION_LANDSCAPE;
            } else if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                config.orientation = Configuration.ORIENTATION_PORTRAIT;
            }
            mRes.updateConfiguration(config, mRes.getDisplayMetrics());
            ViewGroup anotherRootView =
                (ViewGroup) createRootView(LayoutInflater.from(getContext()));
            assertNotNull(anotherRootView);

            mViews.copyLayoutParamsFrom(anotherRootView);

            TestUtil.checkLayoutParams(mRootView, anotherRootView);
        } finally {
            mRes.updateConfiguration(configOrg, mRes.getDisplayMetrics());
        }
    }

    public void testSetButtonPauseImage() {
        Bitmap bitmapPlay = ((BitmapDrawable) mRes.getDrawable(
                android.R.drawable.ic_media_play)).getBitmap();
        Bitmap bitmapPause = ((BitmapDrawable) mRes.getDrawable(
                android.R.drawable.ic_media_pause)).getBitmap();

        ImageView buttonPause = ViewUtil.findViewById(mRootView, R.id.button_pause);
        if (buttonPause == null) {
            mViews.setButtonPauseImage(true);
            mViews.setButtonPauseImage(false);
        } else {
            Bitmap bitmap = ((BitmapDrawable) buttonPause.getDrawable()).getBitmap();
            TestUtil.checkBitmap(bitmapPause, bitmap);

            mViews.setButtonPauseImage(true);
            bitmap = ((BitmapDrawable) buttonPause.getDrawable()).getBitmap();
            TestUtil.checkBitmap(bitmapPlay, bitmap);

            mViews.setButtonPauseImage(false);
            bitmap = ((BitmapDrawable) buttonPause.getDrawable()).getBitmap();
            TestUtil.checkBitmap(bitmapPause, bitmap);
        }
    }

    public void testSetEnabledSeekController() {
        View seekBar = mRootView.findViewById(R.id.seek_bar);
        View buttonFromBegin = mRootView.findViewById(R.id.button_from_begin);
        TextView contributorForbidSeek = ViewUtil.findViewById(mRootView,
                R.id.contributor_forbid_seek);
        if (seekBar == null) {
            assertNull(buttonFromBegin);
            assertNull(contributorForbidSeek);
            mViews.setEnabledSeekController(true);
            mViews.setEnabledSeekController(false);
        } else {
            assertNotNull(buttonFromBegin);
            mViews.setEnabledSeekController(true);
            assertTrue(seekBar.isEnabled());
            assertTrue(buttonFromBegin.isEnabled());
            mViews.setEnabledSeekController(false);
            assertFalse(seekBar.isEnabled());
            assertFalse(buttonFromBegin.isEnabled());

            if (contributorForbidSeek != null) {
                mViews.setContributorForbidSeekVisibility(true);
                assertFalse(seekBar.isEnabled());
                assertFalse(buttonFromBegin.isEnabled());
                mViews.setEnabledSeekController(true);
                assertFalse(seekBar.isEnabled());
                assertFalse(buttonFromBegin.isEnabled());
            }
        }
    }

    public void testGetControllerView() {
        ViewGroup controllerView = mViews.getControllerView();
        assertNotNull(controllerView);
        assertEquals(R.id.player_controller, controllerView.getId());
    }

    public void testSetSeekBarMax() {
        SeekBar seekBar = ViewUtil.findViewById(mRootView, R.id.seek_bar);
        final int second = 12345;
        mViews.setSeekBarMax(second);
        if (seekBar != null) {
            assertEquals(second, seekBar.getMax());
        }
    }

    public void testSetSeekBarProgress() {
        SeekBar seekBar = ViewUtil.findViewById(mRootView, R.id.seek_bar);
        mViews.setSeekBarProgress(98);
        if (seekBar != null) {
            assertEquals(98, seekBar.getProgress());
        }
    }

    public void testSetSeekBarSecondaryProgress() {
        SeekBar seekBar = ViewUtil.findViewById(mRootView, R.id.seek_bar);
        mViews.setSeekBarMax(1000);
        mViews.setSeekBarSecondaryProgress(2, 3);
        if (seekBar != null) {
            assertEquals(666, seekBar.getSecondaryProgress());
        }
    }

    public void testSetSeekBarSecondaryMax() {
        SeekBar seekBar = ViewUtil.findViewById(mRootView, R.id.seek_bar);
        mViews.setSeekBarMax(12345);
        mViews.setSeekBarSecondaryMax();
        if (seekBar != null) {
            assertEquals(12345, seekBar.getSecondaryProgress());
        }
    }

    private class FakeSetOnSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
        boolean onProgressChangedCalled = false;
        boolean onStartTrackingTouchCalled = false;
        boolean onStopTrackingTouchCalled = false;

        public void clearFlag() {
            onProgressChangedCalled = false;
            onStartTrackingTouchCalled = false;
            onStopTrackingTouchCalled = false;
        }
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            onProgressChangedCalled = true;
        }
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            onStartTrackingTouchCalled = true;
        }
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            onStopTrackingTouchCalled = true;
        }
    }
    public void testSetOnSeekBarChangeListener() {
        SeekBar seekBar = ViewUtil.findViewById(mRootView, R.id.seek_bar);

        FakeSetOnSeekBarChangeListener listener = new FakeSetOnSeekBarChangeListener();
        mViews.setOnSeekBarChangeListener(listener);
        assertEquals(listener, mViews.mOnSeekBarChangeListener);
        // TODO 中のコールバックのテストは実装面倒なので省略
    }

    public void testCanUpdateSeekBarProgress() {
        SeekBar seekBar = ViewUtil.findViewById(mRootView, R.id.seek_bar);

        if (seekBar == null) {
            assertFalse(mViews.canUpdateSeekBarProgress());
        } else {
            seekBar.setEnabled(true);
            mViews.mIsTrackingSeekBar = false;
            assertTrue(mViews.canUpdateSeekBarProgress());

            mViews.mIsTrackingSeekBar = true;
            assertFalse(mViews.canUpdateSeekBarProgress());

            seekBar.setEnabled(false);
            mViews.mIsTrackingSeekBar = false;
            assertFalse(mViews.canUpdateSeekBarProgress());
        }
    }

    public void testSetCheckedButtonCommentOnOff() {
        ToggleButton buttonCommentOnOff = ViewUtil.findViewById(mRootView, R.id.button_comment_onoff);
        assertNotNull(buttonCommentOnOff);

        mViews.setCheckedButtonCommentOnOff(false);
        assertFalse(buttonCommentOnOff.isChecked());

        mViews.setCheckedButtonCommentOnOff(true);
        assertTrue(buttonCommentOnOff.isChecked());
    }

    public void testSetContributorForbidSeekVisibility() {
        TextView contributorForbidSeek = ViewUtil.findViewById(mRootView,
                R.id.contributor_forbid_seek);
        if (contributorForbidSeek == null) {
            mViews.setContributorForbidSeekVisibility(true);
            mViews.setContributorForbidSeekVisibility(false);
        } else {
            assertEquals(View.GONE, contributorForbidSeek.getVisibility());
            mViews.setContributorForbidSeekVisibility(true);
            assertEquals(View.VISIBLE, contributorForbidSeek.getVisibility());
            mViews.setContributorForbidSeekVisibility(false);
            assertEquals(View.GONE, contributorForbidSeek.getVisibility());
        }
    }

    private static class FakeOnSendCommentClickListener
    implements PlayerControllerViews.OnSendCommentClickListener {
        public String mail;
        public String body;

        @Override
        public void onClick(String mail, String body) {
            this.mail = mail;
            this.body = body;
        }
    }

    public void testSetOnSendCommentClickListener() {
        FakeOnSendCommentClickListener listener = new FakeOnSendCommentClickListener();

        mViews.setOnSendCommentClickListener(listener);

        EditText commentMail = ViewUtil.findViewById(mRootView,
                R.id.comment_mail);
        EditText commentBody = ViewUtil.findViewById(mRootView,
                R.id.comment_body);
        Button buttonSendComment = ViewUtil.findViewById(mRootView,
                R.id.button_send_comment);
        if (commentMail != null && commentBody != null && buttonSendComment != null) {
            assertEquals("", commentMail.getText().toString());
            assertEquals("", commentBody.getText().toString());
            assertFalse(buttonSendComment.isEnabled());

            commentMail.setText("ue");
            assertFalse(buttonSendComment.isEnabled());

            commentBody.setText("コメント");
            assertTrue(buttonSendComment.isEnabled());

            commentMail.setText("");
            assertTrue(buttonSendComment.isEnabled());

            commentMail.setText("shita");

            assertTrue(buttonSendComment.performClick());
            assertEquals("shita", listener.mail);
            assertEquals("コメント", listener.body);

            assertEquals("shita", commentMail.getText().toString());
            assertEquals("", commentBody.getText().toString());
            assertFalse(buttonSendComment.isEnabled());
        } else {
            assertNull(commentMail);
            assertNull(commentBody);
            assertNull(buttonSendComment);
        }
    }

    public void testEnableComment() {
        EditText commentMail = ViewUtil.findViewById(mRootView,
                R.id.comment_mail);
        EditText commentBody = ViewUtil.findViewById(mRootView,
                R.id.comment_body);
        Button buttonSendComment = ViewUtil.findViewById(mRootView,
                R.id.button_send_comment);
        ImageButton buttonSpeak = ViewUtil.findViewById(mRootView,
                R.id.button_speak);
        if (commentMail != null && commentBody != null
                && buttonSendComment != null && buttonSpeak != null) {
            commentMail.setText("ue");
            commentBody.setText("コメント");

            mViews.disableComment("disable");
            assertFalse(commentMail.isEnabled());
            assertEquals("ue", commentMail.getText().toString());
            assertFalse(commentBody.isEnabled());
            assertEquals("", commentBody.getText().toString());
            assertEquals("disable", commentBody.getHint().toString());
            assertFalse(buttonSpeak.isEnabled());

            mViews.enableComment();
            assertTrue(commentMail.isEnabled());
            assertEquals("ue", commentMail.getText().toString());
            assertTrue(commentBody.isEnabled());
            assertEquals("", commentBody.getText().toString());
            assertNull(commentBody.getHint());
            assertTrue(buttonSpeak.isEnabled());
        } else {
            assertNull(commentMail);
            assertNull(commentBody);
            assertNull(buttonSendComment);
            assertNull(buttonSpeak);
        }
    }

    public void testAddComment() {
        EditText commentBody = ViewUtil.findViewById(mRootView,
                R.id.comment_body);
        if (commentBody != null) {
            assertEquals("", commentBody.getText().toString());

            mViews.addCommentBody("add");
            assertEquals("add", commentBody.getText().toString());

            mViews.addCommentBody("add2");
            assertEquals("addadd2", commentBody.getText().toString());
        }
    }

    private static class FakeSetOnClickListener implements View.OnClickListener {
        public View calledView;

        @Override
        public void onClick(View v) {
            calledView = v;
        }
    }

    public void testSetOnSpeakClickListener() {
        ImageButton buttonSpeak = ViewUtil.findViewById(mRootView,
                R.id.button_speak);
        FakeSetOnClickListener listener = new FakeSetOnClickListener();
        mViews.setOnSpeakClickListener(listener);
        assertNull(listener.calledView);
        if (buttonSpeak != null) {
            assertTrue(buttonSpeak.performClick());
            assertEquals(buttonSpeak, listener.calledView);
        }
    }

    public void testSetSpeakVisibility() {
        ImageButton buttonSpeak = ViewUtil.findViewById(mRootView,
                R.id.button_speak);

        mViews.setSpeakVisibility(false);
        if (buttonSpeak != null) {
            assertEquals(View.GONE, buttonSpeak.getVisibility());
        }

        mViews.setSpeakVisibility(true);
        if (buttonSpeak != null) {
            assertEquals(View.VISIBLE, buttonSpeak.getVisibility());
        }
    }

    private static class FakeOnCommentControllerClickListener implements PlayerControllerViews.OnCommentControllerClickListener {
        public boolean calledOnClick;

        @Override
        public void onClick() {
            calledOnClick = true;
        }
    }

    public void testSetOnCommentControllerClickListener() {
        EditText commentMail = ViewUtil.findViewById(mRootView,
                R.id.comment_mail);
        EditText commentBody = ViewUtil.findViewById(mRootView,
                R.id.comment_body);
        ImageButton buttonSpeak = ViewUtil.findViewById(mRootView,
                R.id.button_speak);
        if (commentMail != null && commentBody != null
                && buttonSpeak != null) {
            FakeOnCommentControllerClickListener listener = new FakeOnCommentControllerClickListener();
            mViews.setOnCommentControllerClickListener(listener);
            assertFalse(listener.calledOnClick);

            assertTrue(commentMail.performClick());
            assertTrue(listener.calledOnClick);

            listener.calledOnClick = false;
            assertTrue(commentBody.performClick());
            assertTrue(listener.calledOnClick);

            listener.calledOnClick = false;
            assertTrue(buttonSpeak.performClick());
            assertTrue(listener.calledOnClick);

            listener.calledOnClick = false;
            assertTrue(commentMail.requestFocus());
            assertTrue(listener.calledOnClick);

            listener.calledOnClick = false;
            assertTrue(commentBody.requestFocus());
            assertTrue(listener.calledOnClick);
        } else {
            assertNull(commentMail);
            assertNull(commentBody);
            assertNull(buttonSpeak);
        }
    }

    public void testSetButtonMoreOnClickListener() {
        ImageButton buttonMore = ViewUtil.findViewById(mRootView,
                R.id.button_more);
        FakeSetOnClickListener listener = new FakeSetOnClickListener();
        mViews.setButtonMoreOnClickListener(listener);
        assertNull(listener.calledView);
        if (buttonMore != null) {
            assertTrue(buttonMore.performClick());
            assertEquals(buttonMore, listener.calledView);
        }
    }

    public void testSetButtonHideOnClickListener() {
        ImageButton buttonHide = ViewUtil.findViewById(mRootView,
                R.id.button_hide);
        FakeSetOnClickListener listener = new FakeSetOnClickListener();
        mViews.setButtonHideOnClickListener(listener);
        assertNull(listener.calledView);
        if (buttonHide != null) {
            assertTrue(buttonHide.performClick());
            assertEquals(buttonHide, listener.calledView);
        }
    }

    protected View createRootView(LayoutInflater inflater) {
        FrameLayout temp = new FrameLayout(getContext());
        return inflater.inflate(R.layout.player_controller, temp, false);
    }
}
