Newer
Older
IrisClient / app / src / main / java / org / ntlab / irisclient / DrawingCardFragment.java
package org.ntlab.irisclient;
import static android.os.Looper.getMainLooper;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.core.os.HandlerCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import org.ntlab.irisclient.models.Drawing;
import org.ntlab.irisclient.viewmodels.GameViewModel;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;

public class DrawingCardFragment extends Fragment {

    private ImageButton[] imageButtons;
    private ImageView[] backColors;
    private Resources resources;
    private GameViewModel gameViewModel;
    // ロングタップで表示させるために必要。非同期で値が格納され、順番通りに保存されないからHashMapにしている
    private Map<Integer, Bitmap> bmImages = new HashMap<>();

    // 下はテストが動くようになったら削除する
    private Map<Integer, Drawing> drawingList = new HashMap<>();  //<dno, drawingのURL>
    private List<Integer> map = new ArrayList<>();  //cno順にdnoを管理(要するに絵の並び)
    private List<String> colorList = new ArrayList<>();  //cno順にr,g,b,dを管理:カードごとの色
    private Boolean isMaster = false;
    // 自分のチームと現在進行中のチームを仮で設定中
    private String myTeam = "r";
    private String nowTurn = "r";

    // コンストラクタ
    public static DrawingCardFragment newInstance(String str){
        // インスタンス生成
        DrawingCardFragment fragment = new DrawingCardFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        gameViewModel = new ViewModelProvider(this).get(GameViewModel.class);

        resources = getResources();
        View view = inflater.inflate(R.layout.fragment_card_drawing,  container, false);

        // ImageButton16個の型を使いまわしやすいように配列で使用
        imageButtons = new ImageButton[] {
                (ImageButton) view.findViewById(R.id.imageButton0),
                (ImageButton) view.findViewById(R.id.imageButton1),
                (ImageButton) view.findViewById(R.id.imageButton2),
                (ImageButton) view.findViewById(R.id.imageButton3),
                (ImageButton) view.findViewById(R.id.imageButton4),
                (ImageButton) view.findViewById(R.id.imageButton5),
                (ImageButton) view.findViewById(R.id.imageButton6),
                (ImageButton) view.findViewById(R.id.imageButton7),
                (ImageButton) view.findViewById(R.id.imageButton8),
                (ImageButton) view.findViewById(R.id.imageButton9),
                (ImageButton) view.findViewById(R.id.imageButton10),
                (ImageButton) view.findViewById(R.id.imageButton11),
                (ImageButton) view.findViewById(R.id.imageButton12),
                (ImageButton) view.findViewById(R.id.imageButton13),
                (ImageButton) view.findViewById(R.id.imageButton14),
                (ImageButton) view.findViewById(R.id.imageButton15)
        };

        backColors = new ImageView[]{
                (ImageView) view.findViewById(R.id.backColour0),
                (ImageView) view.findViewById(R.id.backColour1),
                (ImageView) view.findViewById(R.id.backColour2),
                (ImageView) view.findViewById(R.id.backColour3),
                (ImageView) view.findViewById(R.id.backColour4),
                (ImageView) view.findViewById(R.id.backColour5),
                (ImageView) view.findViewById(R.id.backColour6),
                (ImageView) view.findViewById(R.id.backColour7),
                (ImageView) view.findViewById(R.id.backColour8),
                (ImageView) view.findViewById(R.id.backColour9),
                (ImageView) view.findViewById(R.id.backColour10),
                (ImageView) view.findViewById(R.id.backColour11),
                (ImageView) view.findViewById(R.id.backColour12),
                (ImageView) view.findViewById(R.id.backColour13),
                (ImageView) view.findViewById(R.id.backColour14),
                (ImageView) view.findViewById(R.id.backColour15)
        };

        // Openされた画像ををObserveして、Viewに反映
        gameViewModel.getOpenLiveData().observe (
                getViewLifecycleOwner(),
                openListObserver -> {
                    System.out.println(openListObserver);
                    setOpen(openListObserver);
                }
        );

        gameViewModel.getImageLiveData().observe(
                getViewLifecycleOwner(),
                gameJsonObserver -> {
                    System.out.println("Hello");
                    System.out.println(gameJsonObserver.getDrawingList());
                    setupWithViewModel();
                }
        );

        return view;
    }

    public void onClick(View v) {
        for(int i=0; i< imageButtons.length; i++) {
            if(v.getId() == imageButtons[i].getId())  {
                System.out.println( "タップされたボタンの配列番号:" + i);
                if(nowTurn != myTeam && isMaster == true) { return; }
                confirmAlertMake(i);
            }
        }
    }

    public boolean onLongTap(View v) {

        for(int i=0; i< imageButtons.length; i++) {

            if(v.getId() == imageButtons[i].getId())  {
                System.out.println( "ロングタップされたボタンの配列番号:" + i);
                // 自分のターンのとき、疑い機能のあるアラート表示
                // 相手のターンのとき、画像だけ確認できるアラート表示
                if(nowTurn == myTeam) {
                    doubtAlertMake(i);
                } else {
                    lookImageAlertMake(i);
                }
            }

            // めくられた画像を長押でも確認できるようにする
            if(v.getId() == backColors[i].getId())  {
                System.out.println( "タップされたボタンの配列番号:" + i);
                lookImageAlertMake(i);
            }
        }

        return false;
    }

    private void setupWithViewModel() {
        Iris iris = (Iris) this.getActivity().getApplication();
        myTeam = iris.getTeam();
        drawingList = gameViewModel.getGame().getDrawingList();
        map = gameViewModel.getGame().getMap();
        colorList = gameViewModel.getGame().getColorList();

        Context context = getContext();

        for (int i = 0; i < drawingList.size(); i++) {
            // タップとロングタップのセット
            imageButtons[i].setOnClickListener(this::onClick);
            imageButtons[i].setOnLongClickListener(this::onLongTap);
            backColors[i].setOnLongClickListener(this::onLongTap);

            // 画像のセット
            String urlSt = drawingList.get(map.get(i)).getDrawing();
            setImage(i, urlSt, context);

            System.out.println(colorList.get(i));
            String color = colorList.get(i);
            // 初回だけセットする外枠の、メンバーとマスターで表示分け
            // メンバー:全て肌色、マスター:赤・青・黒・グレーの表示
            if(isMaster == true) {
                if (colorList.get(i).contains("r")) {
                    backColors[i].setBackground(resources.getDrawable(R.drawable.red_image));
                } else if (colorList.get(i).contains("b")) {
                    backColors[i].setBackground(resources.getDrawable(R.drawable.blue_image));
                } else if (colorList.get(i).contains("g")) {
                    backColors[i].setBackground(resources.getDrawable(R.drawable.gray_image));
                } else if (colorList.get(i).contains("d")) {
                    backColors[i].setBackground(resources.getDrawable(R.drawable.black_image));
                } else {
                    System.out.println("本当は...:「" + colorList.get(i) + "」");
                }
            } else {
                backColors[i].setBackground(resources.getDrawable(R.drawable.skin_image));
            }

        }

    }

    /**
     * URLから画像を取得
     * Androidのルール的にメインスレッドで書くとクラッシュする
     * 非同期で書かなければならない
     **/
    private void setImage(int cno, String urlSt, Context context) {
        // Singleの別スレッドを立ち上げる
        Executors.newSingleThreadExecutor().execute(() -> {
            try {
                URL url = new URL(urlSt);
                HttpURLConnection urlCon =  (HttpURLConnection) url.openConnection();

                // タイムアウト設定
                urlCon.setReadTimeout(10000);
                urlCon.setConnectTimeout(20000);

                // リクエストメソッド
                urlCon.setRequestMethod("GET");

                // リダイレクトを自動で許可しない設定
                urlCon.setInstanceFollowRedirects(false);

                InputStream is = urlCon.getInputStream();
                Bitmap originalBMP = BitmapFactory.decodeStream(is);
                Bitmap resizedMiniBMP = resize(originalBMP, (int) convertDp2Px(105, context),(int) convertDp2Px(60, context));
                Bitmap resizedBigBMP = resize(originalBMP, (int) convertDp2Px(420, context),(int) convertDp2Px(240, context));
                bmImages.put(cno, resizedBigBMP);

                HandlerCompat.createAsync(getMainLooper()).post(() ->
                        // Mainスレッドに返す
                        imageButtons[cno].setImageBitmap(resizedMiniBMP)
                );

            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * dpとpxを変換
     * BitMapでImageを描画するためにどうしても必要だった
     **/
    private static float convertDp2Px(float dp, Context context) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        return dp * metrics.density;
    }

    /**
     * 表示させる画像のサイズ調整
     **/
    private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) {
        if (maxHeight > 0 && maxWidth > 0) {

            int width = image.getWidth();
            int height = image.getHeight();
            float ratioBitmap = (float) width / (float) height;
            float ratioMax = (float) maxWidth / (float) maxHeight;

            int finalWidth = maxWidth;
            int finalHeight = maxHeight;
            if (ratioMax > 1) {
                finalWidth = (int) ((float)maxHeight * ratioBitmap);
            } else {
                finalHeight = (int) ((float)maxWidth / ratioBitmap);
            }
            image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
            return image;
        } else {
            return image;
        }
    }

    /**
     * 開けられたImageをViewに反映させる
     * Observeして変更加わった度に呼ばれる
     **/
    private void setOpen(List<Boolean> openList) {
        for(int i=0; i< openList.size(); i++) {
            if (openList.get(i) == true) {
                // オープンだったときの描画
                if (colorList.get(i).contains("r")) {
                    backColors[i].setBackground(resources.getDrawable(R.drawable.red_image));
                    imageButtons[i].setVisibility(View.INVISIBLE);
                } else if (colorList.get(i).contains("b")) {
                    backColors[i].setBackground(resources.getDrawable(R.drawable.blue_image));
                    imageButtons[i].setVisibility(View.INVISIBLE);
                } else if (colorList.get(i).contains("g")) {
                    backColors[i].setBackground(resources.getDrawable(R.drawable.gray_image));
                    imageButtons[i].setVisibility(View.INVISIBLE);
                } else if (colorList.get(i).contains("d")) {
                    backColors[i].setBackground(resources.getDrawable(R.drawable.black_image));
                    imageButtons[i].setVisibility(View.INVISIBLE);
                    finishGameAlertMake(i, myTeam, nowTurn);
                }
                setAnime(i);
            }
        }
    }

    //-----------------------------------------------------------------------------
    // アラート関係の関数
    /**
     * 本当に裏返してよいか確認させるアラート
     */
    private void confirmAlertMake(int cno){
        String strTitle = "注意";
        String strMessage = "本当にカードをめくってよろしいですか?";

        AlertDialog.Builder builder;
        builder = new AlertDialog.Builder(getContext());
        builder.setMessage(strMessage);
        builder.setTitle(strTitle);
        builder.setPositiveButton("ok", (dialog, id) -> setOpenRealTime(cno, true));
        builder.setNegativeButton("キャンセル", (dialog, id) -> setOpenRealTime(cno, false));
        builder.create();
        builder.show();
    }

    /**
     * アラートから呼ばれる、リアルタイムに裏返す処理
     **/
    private void setOpenRealTime(int cno, boolean isOK) {
        // 裏返す処理
        if(isOK) {
            if (colorList.get(cno).contains("r")) {
                backColors[cno].setBackground(resources.getDrawable(R.drawable.red_image));
                imageButtons[cno].setVisibility(View.INVISIBLE);
            } else if (colorList.get(cno).contains("b")) {
                backColors[cno].setBackground(resources.getDrawable(R.drawable.blue_image));
                imageButtons[cno].setVisibility(View.INVISIBLE);
            } else if (colorList.get(cno).contains("g")) {
                backColors[cno].setBackground(resources.getDrawable(R.drawable.gray_image));
                imageButtons[cno].setVisibility(View.INVISIBLE);
            } else if (colorList.get(cno).contains("d")) {
                backColors[cno].setBackground(resources.getDrawable(R.drawable.black_image));
                imageButtons[cno].setVisibility(View.INVISIBLE);
                finishGameAlertMake(cno, myTeam, nowTurn);
            }
            setAnime(cno);
        }
        //TODO: gameViewModel.set〇〇(cno)が完成したら
        //gameViewModel.se

    }

    /**
     * 自分のターンのときに、
     * 疑うか疑わないかのアラートを表示させるコード
     */
    private void doubtAlertMake(int cno){
        String strTitle = "疑いますか?";
        String strMessage = "(ここに画像を表示させる予定)";

        AlertDialog.Builder builder;
        builder = new AlertDialog.Builder(getContext());
        builder.setTitle(strTitle);

        ImageView iv = new ImageView(getContext());
        iv.setImageBitmap(bmImages.get(cno));

        iv.setAdjustViewBounds(true);
        builder.setView(iv);

        builder.setPositiveButton("疑う", (dialog, id) -> setDoubt(cno, true));
        builder.setNegativeButton("キャンセル", (dialog, id) -> setDoubt(cno, false));
        builder.create();
        builder.show();
    }

    /**
     * アラートから呼ばれる、疑いをかける処理
     **/
    private void setDoubt(int cno, boolean isOK) {
        // 疑う処理
    }

    /**
     * 相手のターンのときに、
     * 画像だけ確認できるアラートを表示させるコード
     */
    private void lookImageAlertMake(int cno){
        String strTitle = "";

        AlertDialog.Builder builder;
        builder = new AlertDialog.Builder(getContext());
        builder.setTitle(strTitle);

        ImageView iv = new ImageView(getContext());
        iv.setImageBitmap(bmImages.get(cno));
        iv.setAdjustViewBounds(true);

        builder.setView(iv);

        builder.setPositiveButton("完了", (dialog, id) -> setNone(cno, true));
        builder.create();
        builder.show();
    }

    /**
     * アラートからOKを呼ばれたときにする処理
     * まだ空
     **/
    private void setNone(int cno, boolean isOK) {
    }

    private void setAnime(int cno){
        ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.0f, 1.0f, 0.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        // animation時間 msec
        scaleAnimation.setDuration(2000);

        RotateAnimation rotate = new RotateAnimation(0.0f, 120.0f,
                Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.5f);
        // animation時間 msec
        rotate.setDuration(2000);

        AnimationSet animationSet = new AnimationSet( true );

        // animationSetにそれぞれ追加する
        animationSet.addAnimation( scaleAnimation );
        animationSet.addAnimation( rotate );

        imageButtons[cno].startAnimation(animationSet);
    }

    /**
     * 黒いカードがひかれて、ゲームが終わったときに呼ばれるアラート
     */
    private void finishGameAlertMake(int cno, String myTeam, String nowTurn) {
        try {
            Thread.sleep(2000); //3000ミリ秒Sleepする
        } catch (InterruptedException e) {
        }

        String strTitle;
        String strMessage;

        if (myTeam == nowTurn) {
            strTitle = "Your Lose...";
            strMessage = "お疲れ様でした。\n残念ながら、あなたチームは負けました...";
        } else {
            strTitle = "Your Win!!";
            strMessage = "お疲れ様でした。\nおめでとうございます、あなたチームの勝利です!";
        }

        AlertDialog.Builder builder;
        builder = new AlertDialog.Builder(getContext());
        builder.setTitle(strTitle);
        builder.setMessage(strMessage);
        builder.setPositiveButton("完了", (dialog, id) -> setFinish());
        builder.create();
        builder.show();
    }

    // TODO: 未完成の関数
    /**
     * ゲームが終了したときに呼ばれる関数
     * 画面をトップに戻る動作でも書く?
     **/
    private void setFinish() {
    }

}