package org.mahjong4j;

import org.mahjong4j.hands.MahjongHands;
import org.mahjong4j.hands.MentsuComp;
import org.mahjong4j.yaku.normals.MahjongYakuEnum;
import org.mahjong4j.yaku.normals.NormalYakuResolver;
import org.mahjong4j.yaku.yakuman.MahjongYakumanEnum;
import org.mahjong4j.yaku.yakuman.YakumanResolver;

import java.util.ArrayList;
import java.util.List;

/**
 * 和了判定に関するクラスです。
 * 役の判定は別のクラスで行うがここから呼び出します
 *
 * @author yu1ro
 */
public class Mahjong {

    //付いた役満リスト
    public List<MahjongYakumanEnum> yakumanList = new ArrayList<>(1);

    //付いた通常役リスト
    public List<MahjongYakuEnum> normalYakuList = new ArrayList<>(0);

    //翻
    private int han;

    private MahjongHands hands;

    public Mahjong(MahjongHands hands) {
        this.hands = hands;
    }

    public List<MahjongYakumanEnum> getYakumanList() {
        return yakumanList;
    }

    public List<MahjongYakuEnum> getNormalYakuList() {
        return normalYakuList;
    }

    public void calculate() {
        //和了れない場合は即座に終了
        if (!hands.getCanWin()) return;

        //国士無双の場合はそれ以外ありえないので保存して即座に終了
        if (hands.getIsKokushimuso()) {
            yakumanList.add(MahjongYakumanEnum.KOKUSHIMUSO);
            return;
        }

        //役満を探し見つかれば通常役は調べずに終了
        if (findYakuman()) return;

        findNormalYaku();
    }

    /**
     * @return 役満が見つかったか
     */
    private boolean findYakuman() {
        //役満をストックしておき、見つかったら先にこちらに保存する
        List<MahjongYakumanEnum> yakumanStock = new ArrayList<>(4);

        //それぞれの面子の完成形で判定する
        for (MentsuComp comp : hands.getMentsuCompList()) {
            List<YakumanResolver> yakumanResolverList
                = Mahjong4jYakuConfig.getYakumanResolverList(comp);

            for (YakumanResolver resolver : yakumanResolverList) {
                if (resolver.isMatch()) {
                    yakumanStock.add(resolver.getYakuman());
                }
            }

            //ストックと保存する役満リストと比較し大きい方を保存する
            if (yakumanList.size() < yakumanStock.size()) {
                yakumanList = yakumanStock;
            }
        }

        return yakumanList.size() > 0;
    }

    /**
     *
     */
    public void findNormalYaku() {
        //役をストックしておく
        List<MahjongYakuEnum> yakuStock = new ArrayList<>(7);
        //それぞれの面子の完成形で判定する
        for (MentsuComp comp : hands.getMentsuCompList()) {
            List<NormalYakuResolver> resolverList
                = Mahjong4jYakuConfig.getNormalYakuResolverList(comp);
            for (NormalYakuResolver resolver : resolverList) {
                if (resolver.isMatch()) {
                    yakuStock.add(resolver.getNormalYaku());
                }
            }

            int hanSum = calcHanSum(yakuStock);
            if (hanSum > this.han) {
                han = hanSum;
                normalYakuList = yakuStock;
            }
        }
    }

    /**
     * 手牌が食い下がる形かも判定し、翻の合計を計算し、返します
     *
     * @param yakuStock 役のストック
     * @return 翻数の合計
     */
    private int calcHanSum(List<MahjongYakuEnum> yakuStock) {
        int hanSum = 0;
        if (hands.getIsKuisagari()) {
            for (MahjongYakuEnum yaku : yakuStock) {
                hanSum += yaku.getKuisagari();
            }
        } else {
            for (MahjongYakuEnum yaku : yakuStock) {
                hanSum += yaku.getHan();
            }
        }
        return hanSum;
    }
}

@@ -2206,167 +2206,175 @@
   //
-%E5%BD%B9%E3%82%92%E3%82%B9%E3%83%88%E3%83%83%E3%82%AF%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8F%0A        List%3CMahjongYakuEnum%3E yakuStock = new ArrayList%3C%3E(7);%0A        //%E3%81%9D%E3%82%8C%E3%81%9E%E3%82%8C%E3%81%AE%E9%9D%A2%E5%AD%90%E3%81%AE%E5%AE%8C%E6%88%90%E5%BD%A2%E3%81%A7%E5%88%A4%E5%AE%9A%E3%81%99%E3%82%8B%0A        for (MentsuComp comp : hands.getMentsuCompList()) %7B
+%E3%81%9D%E3%82%8C%E3%81%9E%E3%82%8C%E3%81%AE%E9%9D%A2%E5%AD%90%E3%81%AE%E5%AE%8C%E6%88%90%E5%BD%A2%E3%81%A7%E5%88%A4%E5%AE%9A%E3%81%99%E3%82%8B%0A        for (MentsuComp comp : hands.getMentsuCompList()) %7B%0A            //%E5%BD%B9%E3%82%92%E3%82%B9%E3%83%88%E3%83%83%E3%82%AF%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8F%0A            List%3CMahjongYakuEnum%3E yakuStock = new ArrayList%3C%3E(7);
 %0A   

fix timing of initialize yakuStock