package jp.co.y_net.amm.page;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import jp.co.y_net.amm.AppSession;
import jp.co.y_net.amm.AppSession.LoginUser;
import jp.co.y_net.amm.common.AppStringUtils;
import jp.co.y_net.amm.common.AppUtils;
import jp.co.y_net.amm.common.ResourceReader;
import jp.co.y_net.amm.dao.Grp;
import jp.co.y_net.amm.dao.Grpusr;
import jp.co.y_net.amm.dao.Usr;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigator;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.PageableListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;

public class GroupListPage extends CommonFrameA {
    private static final long serialVersionUID = 1L;

    /*
     * 画面入力値
     */
    /* グループ作成.名称 */
    private String groupnameValue = "";
    
    /**
     * ログインチェック定義
     * @see jp.co.y_net.amm.page.AppPage#validateLogin()
     */
    @Override
    public boolean validateLogin() {
        if(AppSession.get().isLogin()) {
            return true;
        }
        return false;
    }
    
    public GroupListPage(PageParameters pageParams) {
        
        /* 共通戻るリンクの設置 */
        createCommonBackLinks();
        
        /* フィードバックメッセージ */
        final FeedbackPanel feedbackPanel = new FeedbackPanel("feedback");
        feedbackPanel.setOutputMarkupId(true);
        add(feedbackPanel);
        
        /* 入力フォーム */
        Form<Void> form  = new Form<Void>("form");
        add(form);
        
        /* 初期表示エラーチェック・共通変数設定 --------------------------------------------------------------------- */
        
        /*
         * 機能制御
         */
        if (ResourceReader.getBooleanQuick("enable.grouplist") == false) {
            form.setVisible(false);
            error("現在この機能はご利用いただけません。");
        }
        
        
        form.setVisible(false); // Formはエラーチェックが完了するまで非表示とする。

        final LoginUser loginUser  = AppSession.get().getLoginUser();
        if(loginUser == null) {
            error("ログイン情報が取得できません。");
            return;
        }
        final Integer loginUserId = loginUser.getUsrid();
        
        if(hasInputError()) return; // ----------エラーがあれば中止
        form.setVisible(true);
        
        /* Form内の設定 ----------------------------------------------------------------------------------------------*/
        /* 完了メッセージ */
        Model<String> resultMessageModel = new Model<String>() {
//            @Override
//            public String getObject() {
//                if(complete) {
//                    return "";
//                }
//                return "";
//            }
        };
        final Label resutlMessage = new Label("resutlMessage", resultMessageModel);
        resutlMessage.setOutputMarkupId(true);
        form.add(resutlMessage);
        
        /* -----------------------------------------------------------------------------------------------------------*/
        
        /*
         * listA = 管理グループ一覧のモデル
         *  リクエストごとにloadが実行される
         */
        final IModel<List<Grp>> listAModel = new LoadableDetachableModel<List<Grp>>() {
            /*  */
            @Override
            protected List<Grp> load() {
                
                Grp cndGrp = new Grp();
                
                if(Usr.KIND_運営管理者 == loginUser.getKind()) {
                    // 運営管理者は全て表示
                } else {
                    cndGrp.setAdminusrid(loginUserId); // 自分の管理しているグループに絞り込む
                }
                
                List<Grp> list = grpDao.get(cndGrp);
                
                /* 作成日の新しい順でソート*/
                Collections.sort(list, new Grp.CreatedateComparator(true));
                return list;
            }
            
        };
        /*
         * listB = 参加グループ一覧のモデル
         *  リクエストごとにloadが実行される
         */
        final IModel<List<Grpusr>> listBModel = new LoadableDetachableModel<List<Grpusr>>() {
            @Override
            protected List<Grpusr> load() {
                Grpusr cndGrpusr = new Grpusr();
                cndGrpusr.setUsrid(loginUserId);
                List<Grpusr> list = grpusrDao.get(cndGrpusr);
                
                /* 
                 *・自分が管理者のグループは除外する
                 *・脱退者は除外する
                 */
                List<Grpusr> tmp = new ArrayList<Grpusr>();
                for(Grpusr gu: list) {
                    Grp g = grpDao.getByGrpid(gu.getGrpid());
                    if(g == null) {
                        // 追加しない
                    } else if(g.getAdminusrid().equals(loginUserId)) {
                        // 追加しない
                    } else if(Grpusr.STATUS_脱退.equals(gu.getStatus())) {
                        // 追加しない
                    } else {
                        tmp.add(gu);
                    }
                    
                }
                list = tmp;
                
                /* 参加日の新しい順でソート*/
                Collections.sort(list, new Grpusr.JoindateComparator(true));
                return list;
            }
        };
        
        
        /* コンテナの設定 ------------------------------------------------------------------------------------------------*/
        /* 
         * 画面の部分更新の対象となるコンテナ
         * 　ページをインスタンス化するときに初期非表示としてはいけない。
         */
        
        /* 管理グループ一覧 */
        final WebMarkupContainer listAContainer = new WebMarkupContainer("listAContainer");
        listAContainer.setOutputMarkupId(true);
        form.add(listAContainer);
        
        final WebMarkupContainer listAContainerData = new WebMarkupContainer("listAContainerData"){
            @Override
            public boolean isVisible() {
                return listAModel.getObject().isEmpty() == false;
            }
        };
        listAContainerData.setOutputMarkupPlaceholderTag(true);// 初期非表示の場合に、後から表示できるようにする
        listAContainer.add(listAContainerData);
        
        final WebMarkupContainer listAContainerNoData = new WebMarkupContainer("listAContainerNoData"){
            @Override
            public boolean isVisible() {
                return listAModel.getObject().isEmpty();
            }
        };
        listAContainerNoData.setOutputMarkupPlaceholderTag(true);// 初期非表示の場合に、後から表示できるようにする
        listAContainer.add(listAContainerNoData);
        
        /* 参加グループ一覧 */
        final WebMarkupContainer listBContainer = new WebMarkupContainer("listBContainer");
        listBContainer.setOutputMarkupId(true);
        form.add(listBContainer);
        
        final WebMarkupContainer listBContainerData = new WebMarkupContainer("listBContainerData"){
            @Override
            public boolean isVisible() {
                return listBModel.getObject().isEmpty() == false;
            }
        };
        listBContainerData.setOutputMarkupPlaceholderTag(true);// 初期非表示の場合に、後から表示できるようにする
        listBContainer.add(listBContainerData);
        
        final WebMarkupContainer listBContainerNoData = new WebMarkupContainer("listBContainerNoData"){
            @Override
            public boolean isVisible() {
                return listBModel.getObject().isEmpty();
            }
        };
        listBContainerNoData.setOutputMarkupPlaceholderTag(true);// 初期非表示の場合に、後から表示できるようにする
        listBContainer.add(listBContainerNoData);
        
        /* 一覧の設定 ------------------------------------------------------------------------------------------------*/
        
        
        /*listA = 管理グループ一覧 ------------------------------------------------------------------- */
        final PageableListView<Grp> listA = new PageableListView<Grp>("listA", listAModel, 5) {
            private static final long serialVersionUID = 1L;
            @Override
            protected void populateItem(ListItem<Grp> item) {
                
                final Grp grp = item.getModelObject();

                item.add(new Label("groupname", grp.getName())); // グループ名
                item.add(new Label("createdate" , AppUtils.toStrYyyyMMdd(grp.getCreatedate()))); // 作成日
                item.add(new Label("membercount" , grpusrDao.getMembercount参加中AsString(grp.getGrpid()))); // 参加人数
                
                String adminname = usrDao.getByUsrid(grp.getAdminusrid()).getName();
                item.add(new Label("leadername" , adminname)); // 管理者
                
                /* 「メンバーリストへ」*/
                PageParameters param = new PageParameters();
                param.add("grpid", grp.getGrpid());
                item.add(new BookmarkablePageLink<Void>("goMemberlist", GroupMemberListPage.class, param));
                
                /* グループ削除 ボタン */
                item.add(new ConfirmAjaxButton("buttonDelete"){
                    
                    @Override
                    protected String getConfirmMessage() {
                        return "すべてのメンバーを脱退させ、グループを削除します。";
                    }
                    @Override
                    void executableWork() {
                        /* データ操作 */
                        grpDao.removeLogical(grp, loginUserId); // 【論理削除】
                        
                        // 紐づくメンバーも削除
                        Grpusr members = new Grpusr();
                        members.setGrpid(grp.getGrpid());
                        for(Grpusr member: grpusrDao.get(members)) {
                            member.set脱退設定();
                            grpusrDao.update(member, loginUserId);
                        }
                    }
                    @Override
                    void executeAfter(AjaxRequestTarget target) {
                        
                        /* メッセージ表示 */
                        feedbackPanel.info(grp.getName() + " のすべてのメンバーを脱退させ、グループを削除しました。");
//                        /* LoadableDetachableModel#load を再実行させるためのデタッチ */
//                        listAModel.detach(); 
                        
                        target.add(listAContainer);
                    }
                });
            }
        };
        listAContainerData.add(listA);
        
        /* ページングの部品 */
        final AjaxPagingNavigator pagingListA = new AjaxPagingNavigator("pagingListA", listA){};
        listAContainerData.add(pagingListA);

        
        /* グループ作成.名称 */
        TextField<String> inputgroupname = new TextField<String>("inputgroupname", new PropertyModel<String>(this, "groupnameValue"));
        listAContainer.add(inputgroupname);
        
        /* グループを作成する ボタン */
        listAContainer.add(new ConfirmAjaxButton("buttonCreateGroup"){
            @Override
            protected String getConfirmMessage() {
                return "グループを作成します。";
            }
            @Override
            boolean executeBefore() {
                /* 入力値変換 */
                groupnameValue = AppStringUtils.trim(groupnameValue);
                /* 入力値検査 */
                validItem(groupnameValue, "グループ名", 1, 512);
                if(hasInputError()) return false; // ここまででエラーチェック
                return true;
            }
            @Override
            void executableWork() {
                /* データ更新 */
                Grp group = new Grp();
                group.setName(groupnameValue);
                group.setAdminusrid(loginUser.getUsrid());
                group.setCreatedate(AppUtils.createNowLong());
                grpDao.add(group, loginUserId); // 【データ更新】
                
                Grpusr member = new Grpusr();
                member.setGrpid(group.getGrpid());
                member.setUsrid(loginUser.getUsrid());
                member.setJoindate(AppUtils.createNowLong());
                member.setAdmindate(AppUtils.createNowLong());
                member.setStatus(Grpusr.STATUS_参加中);
                grpusrDao.add(member, loginUserId); // 【データ更新】
            }
            @Override
            void executeAfter(AjaxRequestTarget target) {
                
                /* メッセージ表示 */
                feedbackPanel.info("グループ「" + groupnameValue + "」を作成しました。");
                
                /* 入力項目初期化 */
                groupnameValue = "";
                
                /* 画面部品の更新 */
                target.add(listAContainer); // 管理グループ一覧領域
            }
        });


        /*listB = 参加グループ一覧 ------------------------------------------------------------------- */
        
        final PageableListView<Grpusr> listB = new PageableListView<Grpusr>("listB", listBModel, 20) {
            private static final long serialVersionUID = 1L;
            @Override
            protected void populateItem(ListItem<Grpusr> item) {
                
                final Grpusr grpusr = item.getModelObject();
                final Grp grp = grpDao.getByGrpid(grpusr.getGrpid());
                
                final String groupname = grp.getName();

                item.add(new Label("groupname", groupname)); // グループ名
                item.add(new Label("membercount" , grpusrDao.getMembercount参加中AsString(grp.getGrpid()))); // 参加人数
                
                String adminname = usrDao.getByUsrid(grp.getAdminusrid()).getName();
                item.add(new Label("leadername" , adminname)); // 管理者
                
                
                Date joindate = AppUtils.toDate(grpusr.getJoindate());
                String joindateStr = "";
                if(joindate != null) {
                    joindateStr = AppUtils.toStrYyyyMMdd(joindate);
                }
                item.add(new Label("joindate" , joindateStr)); // 参加日
                item.add(new Label("status" , grpusr.getStatus合算())); // 状態
                
                
                /* 参加する ボタン */
                item.add(new ConfirmAjaxButton("buttonJoin"){
                    @Override
                    protected String getConfirmMessage() {
                        return "グループ「" + groupname + "」に参加します。";
                    }
                    @Override
                    void executableWork() {
                        /* データ操作 */
                        grpusr.setJoindate(AppUtils.createNowLong()); // 参加日時
                        grpusr.setStatus(Grpusr.STATUS_参加中);
                        grpusrDao.update(grpusr, loginUserId); // 【データ更新】
                    }
                    @Override
                    void executeAfter(AjaxRequestTarget target) {
                        
                        /* メッセージ表示 */
                        feedbackPanel.info("グループ「" + groupname + "」に参加しました。");

                        /* 画面部品の更新 */
                        target.add(listBContainer); // 参加グループ一覧領域
                    }
                    @Override
                    public boolean isVisible() {
                        /* 招待中状態で無ければ非表示 */
                        if(Grpusr.STATUS_招待中.equals(grpusr.getStatus()) == false) return false;
                        
                        return true;
                    }
                });
                /* 参加しない ボタン */
                item.add(new ConfirmAjaxButton("buttonReject"){
                    @Override
                    protected String getConfirmMessage() {
                        return "グループ「" + groupname + "」への参加を辞退します。";
                    }
                    @Override
                    void executableWork() {
                        /* データ操作 */
                        grpusrDao.removeLogical(grpusr, loginUserId); // 【論理削除】
                    }
                    @Override
                    void executeAfter(AjaxRequestTarget target) {
                        
                        /* メッセージ表示 */
                        feedbackPanel.info("グループ「" + groupname + "」への参加を辞退しました。");
                        
                        /* 画面部品の更新 */
                        target.add(listBContainer); // 参加グループ一覧領域
                    }
                    @Override
                    public boolean isVisible() {
                        /* 招待中状態で無ければ非表示 */
                        if(Grpusr.STATUS_招待中.equals(grpusr.getStatus()) == false) return false;
                        
                        return true;
                    }
                });
                /* 脱退する ボタン */
                item.add(new ConfirmAjaxButton("buttonLeave"){
                    @Override
                    protected String getConfirmMessage() {
                        return "グループ「" + groupname + "」から脱退します。";
                    }
                    @Override
                    void executableWork() {
                        /* データ操作 */
                        grpusr.set脱退設定();
                        grpusrDao.update(grpusr, loginUserId); // 【データ更新】
                    }
                    @Override
                    void executeAfter(AjaxRequestTarget target) {
                        
                        /* メッセージ表示 */
                        feedbackPanel.info("グループ「" + groupname + "」から脱退しました。");
                        
                        /* 画面部品の更新 */
                        target.add(listBContainer); // 参加グループ一覧領域
                    }
                    @Override
                    public boolean isVisible() {
                        if (Grpusr.STATUS_参加中.equals(grpusr.getStatus()) == false) return false;
                        return true;
                    }
                });
                
                /* 承諾する ボタン */
                item.add(new ConfirmAjaxButton("buttonAdminAccept"){
                    @Override
                    protected String getConfirmMessage() {
                        return "グループ「" + groupname + "」の管理者を承諾します。";
                    }
                    @Override
                    void executableWork() {
                        /* データ操作 */
                        grpusr.setAdmindate(AppUtils.createNowLong()); // 管理者就任日時
                        grpusr.setStatusadmin(Grpusr.STATUS_ADMIN_移管完了);
                        grpusrDao.update(grpusr, loginUserId); // 【データ更新】
                        
                        grp.setAdminusrid(loginUser.getUsrid());
                        grpDao.update(grp, loginUserId); // 【データ更新】
                    }
                    @Override
                    void executeAfter(AjaxRequestTarget target) {
                        
                        /* メッセージ表示 */
                        feedbackPanel.info("グループ「" + groupname + "」の管理者を承諾しました。");
                        
                        /* 画面部品の更新 */
                        target.add(listAContainer); // 管理グループ一覧領域
                        target.add(listBContainer); // 参加グループ一覧領域
                    }
                    @Override
                    public boolean isVisible() {
                        /* 移管依頼中でなければ表示しない */
                        if(Grpusr.STATUS_ADMIN_移管依頼中.equals(grpusr.getStatusadmin()) == false) return false;
                        return true;
                    }
                });
                /* 承諾しない ボタン */
                item.add(new ConfirmAjaxButton("buttonAdminReject"){
                    @Override
                    protected String getConfirmMessage() {
                        return "グループ「" + groupname + "」の管理者を辞退します。";
                    }
                    @Override
                    void executableWork() {
                        /* データ操作 */
                        grpusr.setStatusadmin(Grpusr.STATUS_ADMIN_未設定);
                        grpusrDao.update(grpusr, loginUserId); // 【データ更新】
                    }
                    @Override
                    void executeAfter(AjaxRequestTarget target) {
                        
                        /* メッセージ表示 */
                        feedbackPanel.info("グループ「" + groupname + "」の管理者を辞退しました。");
                        
                        /* 画面部品の更新 */
                        target.add(listBContainer); // 参加グループ一覧領域
                    }
                    @Override
                    public boolean isVisible() {
                        /* 移管依頼中でなければ表示しない */
                        if(Grpusr.STATUS_ADMIN_移管依頼中.equals(grpusr.getStatusadmin()) == false) return false;
                        return true;
                    }
                });
            }
        };
        listBContainerData.add(listB);
        
        /* ページングの部品 */
        final AjaxPagingNavigator pagingListB = new AjaxPagingNavigator("pagingListB", listB){};
        listBContainerData.add(pagingListB);
        
    }


}
