package jp.co.y_net.amm.page;

import java.util.ArrayList;
import java.util.Collections;
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.AppLogger;
import jp.co.y_net.amm.common.AppSendMail;
import jp.co.y_net.amm.common.AppSendMail.MailSetting;
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.AppDef;
import jp.co.y_net.amm.dao.Org;
import jp.co.y_net.amm.dao.Usr;

import org.apache.commons.lang.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.PageableListView;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
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;

/**
 * @author k_inaba
 */
public class MemberListPage extends CommonFrameA {
    private static final long serialVersionUID = 1L;
    
    /*
     * 画面入力値
     */
    public String usrnameValue;
    public String usrmailValue;
    public String usrmail2Value;
    
    /*
     * 画面の状態
     */
    private boolean complete = false;
    
    /* 編集対象の組織 */
    private Org targetOrg = null;
    
    
    
    /**
     * ログインチェック定義
     * @see jp.co.y_net.amm.page.AppPage#validateLogin()
     */
    @Override
    public boolean validateLogin() {
        if(AppSession.get().isLogin()) {
            if(AppSession.get().getLoginUser().getKind().equals(Usr.KIND_運営管理者)) {
                return true;
            }
            if(AppSession.get().getLoginUser().getKind().equals(Usr.KIND_機関管理者)) {
                return true;
            }
//            if(AppSession.get().getLoginUser().getKind().equals(Usr.KIND_機関会員)) {
//                error("権限がありません。");
//                return false;
//            }
        }
        return false;
    }
    
    public MemberListPage(PageParameters pageParams) {
        
        /* 共通戻るリンクの設置 */
        createCommonBackLinks();
        
        /* 画面固有の戻るボタンの設置 */
        createBackLink(OrgMemberListPage.class, "登録会員情報管理");
        
        /* フィードバックパネルの設置 */
        createFeedbackPanel();

        final Form<Void> form  = new Form<Void>("form");
        add(form);
        
        Label h1msg = new Label("h1msg", "");
        form.add(h1msg);
        
        /* 見出し */
        form.add(new Label("h2msg", new Model<String>(){
            @Override
            public String getObject() {
                if(mode運営管理者一覧() == false) {
                    return "追加";
                } else {
                    return "運営管理者の追加";
                }
            }
        }));

        
        WebMarkupContainer contMemberList = new WebMarkupContainer("contMemberList");
        form.add(contMemberList);
        
        /* 見出し */
        contMemberList.add(new Label("h2msg", new Model<String>(){
            @Override
            public String getObject() {
                if(mode運営管理者一覧() == false) {
                    return "会員";
                } else {
                    return "運営管理者";
                }
            }
        }));
        
        
        /* 初期表示エラーチェック ----------------------------------------------------------------------------------- */
        form.setVisible(false); // Formはエラーチェックが完了するまで非表示とする。
        contMemberList.setVisible(false);

        final LoginUser loginUser  = AppSession.get().getLoginUser();
        if(loginUser == null) {
            error("ログイン情報が取得できません。");
            return; // ----------中断
        }
        final Integer loginUserId = loginUser.getUsrid();
        
        
        /*
         * 表示対象の決定
         * ・パラメータに orgid が設定されている場合は、該当する組織を対象とする。
         * 　　ただし、ログインユーザが 運営管理者か、その組織の代表者でなければいけない。
         * ・パラメータに orgid が設定されていない場合は、ログインユーザに紐づく組織を対象とする。
         */
        String paramOrgid = pageParams.get("orgid").toString("");
        Integer targetOrgid = null;
        if(StringUtils.isEmpty(paramOrgid) == false) {
            targetOrgid = AppUtils.toInteger(paramOrgid);
            this.targetOrg = orgDao.getByOrgid(targetOrgid);
            
            if(this.targetOrg == null) {
                error("組織情報が取得できません。 orgid=" + paramOrgid);
                return; // ----------中断
            }
            if(isSystemAdmin()) {
                // OK
            } else if(isOrgAdmin()) {
                if (this.targetOrg.getOrgid().equals(loginUser.getOrgid())) {
                    // OK
                } else {
                    error("該当する情報を扱う権限がありません。");
                    return; // ----------中断
                }
            } else {
                error("該当する情報を扱う権限がありません。");
                return; // ----------中断
            }
        } else {
            targetOrgid = loginUser.getOrgid();
            this.targetOrg = orgDao.getByOrgid(targetOrgid);
        }
        
        if(hasInputError()) return; // ----------エラーがあれば中止
        
        /* 組織が「個人」であれば、組織情報編集ページへ遷移させる */
        if(Org.KIND_PERSONAL == this.targetOrg.getKind()) {
            PageParameters param = new PageParameters();
            param.add("orgid", this.targetOrg.getOrgid());
            throw new RestartResponseException(OrgDetailPage.class, param);
        }
        
        
        form.setVisible(true);
        contMemberList.setVisible(true);
        
        /* Form内の設定 ----------------------------------------------------------------------------------------------*/

        h1msg.setDefaultModelObject("会員管理 「" +targetOrg.getName() + "」");
        
        /* 完了メッセージ */
        Model<String> resultMessageModel = new Model<String>() {
            @Override
            public String getObject() {
                if(complete) {
//                    return "仮登録を行い、登録したメールアドレスへ会員追加メールを送りました。";
                    /* 連続登録を想定し、infoメッセージとする。 */
                }
                return "";
            }
        };
        final Label resutlMessage = new Label("resutlMessage", resultMessageModel);
        form.add(resutlMessage);
        /* 出力コンポーネントの設定 ----------------------------------------------------------------------------------*/
        form.add(new Label("thLoginid", new Model<String>(){
            @Override
            public String getObject() {
                if(mode運営管理者一覧() == false) {
                    return "メールアドレス";
                } else {
                    return "ログインID";
                }
            }
        }));
        form.add(new Label("thLoginid2", new Model<String>(){
            @Override
            public String getObject() {
                if(mode運営管理者一覧() == false) {
                    return "メールアドレス確認用";
                } else {
                    return "ログインID確認用";
                }
            }
        }));
        
        
        /* 入力コンポーネントの設定 ----------------------------------------------------------------------------------*/
        TextField<String> usrname = new TextField<String>("usrname", new PropertyModel<String>(this, "usrnameValue"));
        form.add(usrname);
        TextField<String> usrmail = new TextField<String>("usrmail", new PropertyModel<String>(this, "usrmailValue"));
        form.add(usrmail);
        TextField<String> usrmail2 = new TextField<String>("usrmail2", new PropertyModel<String>(this, "usrmail2Value"));
        form.add(usrmail2);
        
        /* 一覧の設定 */
        final WebMarkupContainer listViewContainer = new WebMarkupContainer("listViewContainer");
        contMemberList.add(listViewContainer);
        listViewContainer.setOutputMarkupId(true);
        
        // LoadableDetachableModel は リクエストの最初に load にてデータを取得するモデル
        final IModel<List<Usr>> usrModel = new LoadableDetachableModel<List<Usr>>() {
            @Override
            protected List<Usr> load() {
                Usr cnd = new Usr();
                cnd.setOrgid(targetOrg.getOrgid()); // 該当機関
                Usr cndNot = new Usr();
                cndNot.setStatus(Usr.STATUS_退会);
                List<Usr> list = usrDao.get(cnd, cndNot);
                
                /* 最終ログイン日の新しい順でソート*/
                Collections.sort(list, new Usr.LastlogindateComparator(true));
                
                return list;
            }
        };
        final PageableListView<Usr> listview = new PageableListView<Usr>("listview", usrModel, 20) {
            private static final long serialVersionUID = 1L;
            @Override
            protected void populateItem(ListItem<Usr> item) {
                
                final Usr member = item.getModelObject();
                
                /* 氏名リンク */
                final PageParameters param = new PageParameters();
                param.add("usrid", member.getUsrid());
                //BookmarkablePageLink<Void> lnkName = new BookmarkablePageLink<Void>("lnkName", MemberDetailPage.class, param);
                Link<Void> lnkName = new Link<Void>("lnkName") {
                    @Override
                    public void onClick() {
                        MemberDetailPage nextPage = new MemberDetailPage(param);
                        nextPage.setReturnPage(getPage()); // このページを戻り先として記録する
                        setResponsePage(nextPage);
                    }
                    @Override
                    protected boolean isLinkEnabled() {
                        /* 組織の管理者は 登録情報編集画面を使用するため、会員詳細ページへリンクさせない */
                        if(Usr.ROLE_管理者 == member.getOrgrole()) {
                            return false;
                        }
                        return super.isLinkEnabled();
                    }
                    
                };
                
                Label lnklblName = new Label("lnklblName", member.getName_Disp());
                lnkName.add(lnklblName);
                item.add(lnkName);
                
                /* メールアドレス */
                item.add(new Label("mail", member.getLoginid_Disp()));
                
                /* ステータス */
                item.add(new Label("status", member.getStatus_Disp()));
                
                /* 最終ログイン日時 */
                item.add(new Label("lastlogin" , member.getLastlogindate_Disp()));
            }
        };
        listViewContainer.add(listview);
        
        PagingNavigator navigator = new PagingNavigator("paging", listview){
            @Override
            public boolean isVisible() {
                return listview.size() > 0;
            }
        };
        contMemberList.add(navigator);
        
        /* 処理ボタン定義 --------------------------------------------------------------------------------------------*/
        Button btnSubmit = new ConfirmAjaxButton("btnSubmit"){
            @Override
            String getConfirmMessage() {
                if(mode運営管理者一覧() == false) {
                    return "会員を追加します。";
                } else {
                    return "運営管理者を追加します。";
                }
            }
            @Override
            boolean executeBefore() {
                /* 入力値変換 */
                usrnameValue = AppStringUtils.trim(usrnameValue);
                usrmailValue = AppStringUtils.trimHalf(usrmailValue);
                usrmail2Value = AppStringUtils.trimHalf(usrmail2Value);
                
                /* 入力値検査 */
                validItem(usrnameValue, "氏名", 1, 512);
                if(mode運営管理者一覧() == false) {
                    validItemMail(usrmailValue, "メールアドレス");
                    validItemMail(usrmail2Value, "メールアドレス確認用");
                } else {
                    validItem(usrmailValue, "ログインID", 1, 256);
                    validItem(usrmail2Value, "ログインID確認用", 1, 256);
                }

                if(hasInputError()) return false; // ここまででエラーチェック

                
                if(usrmailValue.equals(usrmail2Value) == false) {
                    if(mode運営管理者一覧() == false) {
                        error("メールアドレスが一致しません。");
                    } else {
                        error("ログインIDが一致しません。");
                    }
                }
                
                if(mailAddressCheck.exist(usrmailValue)) {
                    if(mode運営管理者一覧() == false) {
                        error("このメールアドレスは既に使用されています。");
                    } else {
                        error("このログインIDは既に使用されています。");
                    }
                    
                }
                
                Usr cnd = new Usr();
                cnd.setOrgid(targetOrg.getOrgid()); // 該当機関
                List<Usr> members = usrDao.get(cnd);
                List<Usr> members退会者以外 = new ArrayList<Usr>();
                for(Usr usr: members) {
                    if(usr.getStatus().equals(Usr.STATUS_退会) == false) {
                        members退会者以外.add(usr);
                    }
                }
                if(targetOrg.isLimitnum指定なし() == false
                        && targetOrg.getLimitnum() < members退会者以外.size() + 1) { // 管理者分＋1
                    error("登録可能会員数を超過するため、これ以上登録できません。");
                }
                

                
                if(hasInputError()) return false; // ここまででエラーチェック
                
                return true;
            }
            @Override
            void executeAfter(AjaxRequestTarget target) {
                if(mode運営管理者一覧()) {
                    
                    /* 運営管理者追加 */
                    
                    Usr usr運営管理者 = Usr.create運営管理者(targetOrg, usrmailValue, usrnameValue, false);
                    usrDao.add(usr運営管理者, loginUserId); // 更新処理

                    /* 完了メッセージ */
                    info("運営管理者を追加しました。");
                    
                }else{
                    /* データアクセス 機関管理者による会員仮登録  */
                    Usr usr = new Usr();
                    usr.setLoginid(usrmailValue);
                    usr.setName(usrnameValue);
                    usr.setOrgid(targetOrg.getOrgid());
                    usr.setKind(Usr.KIND_機関会員);
                    usr.setOrgrole(Usr.ROLE_通常会員);
                    usr.setStoplogin(AppDef.FLASE);
                    usr.setStatus(Usr.STATUS_仮登録);
                    usr.setLoginerrorcount(0);
                    
                    usrDao.add(usr, loginUserId); // 【更新処理】

                    /* 共通機能：パスワード登録チケット発行 からチケットを取得する */
                    String random = passwordTicketManager.execute新規パスワード発行(usr.getUsrid());
                    
                    /* 会員追加メール送信 */
                    MailSetting setting = new MailSetting();
                    setting.setTemplate(ResourceReader.getText("message/mail.addmember"));
                    setting.setMailTo(usrmailValue);
                    setting.replace("機関名称", targetOrg.getName());
                    setting.replace("氏名", usrnameValue);
                    String 本登録URL = ResourceReader.getStringQuick("urlroot") + "entrypassword?value=" + random;
                    setting.replace("本登録URL", 本登録URL);
                    boolean sendmailrsult = AppSendMail.send(setting);
                    if(sendmailrsult == false) {
                        error("メールの送信に失敗しました。");
                    }
                    
                    /* テスト自動化対応 */
                    if (AppLogger.isDebug()) {
                        //info("メールに記載したURL【" + 本登録URL + "】");
                        addDebugUrl(本登録URL);
                    }
                    
                    /* 完了メッセージ */
                    info("仮登録を行い、登録したメールアドレスへ会員追加メールを送りました。");
                }
                
                
                /*
                 * 状態遷移
                 * 　この画面では連続して登録することを想定するため、状態遷移は行わない
                 */
//              complete = true;
                
                /* 入力項目初期化 */
                usrnameValue = "";
                usrmailValue = "";
                usrmail2Value = "";
                
                /* コンポーネント更新 */
                target.add(form);
                
            }
            @Override
            public boolean isVisible() {
                /* 完了後の状態ならボタンを表示しない */
                return complete == false;
            }
            @Override
            public boolean isEnabled() {
                /* 運営管理組織のとき、代表者以外は運営管理者を追加できない。 */
                if(mode運営管理者一覧() && isSystemAdmin代表者() == false) {
                    return false;
                }
                return true;
            }
        };
        if(mode運営管理者一覧() == false) {
            btnSubmit.add(new AttributeModifier("value", "会員を追加"));
        } else {
            btnSubmit.add(new AttributeModifier("value", "運営管理者を追加"));
        }
        
        form.add(btnSubmit);
        form.add(new Label("msgNoneBtnSubmit", "このユーザはシステム管理者の追加はできません。"){

            @Override
            public boolean isVisible() {
                return form.get("btnSubmit").isEnabled() == false;
            }
            
        });
        
        
    }
    private boolean mode運営管理者一覧() {
        if(targetOrg != null && Org.KIND_運営管理 == targetOrg.getKind()) {
            if(isSystemAdmin()) {
                return true;
            }
        }
        return false;
    }
}
