package jp.co.y_net.amm.page;

import jp.co.y_net.amm.AppSession;
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.ResourceReader;
import jp.co.y_net.amm.service.PasswordTicketManager;

import org.apache.commons.lang.StringUtils;
import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
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.link.ExternalLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.Model;



/**
 * １カラムでデザインされたページの共通クラス
 * 
 * ヘッダー領域
 * ・トップぺ戻るリンク
 * ・ログイン中のユーザID
 * ・ログアウトボタン
 * 
 * フッター領域
 * 
 * @author k_inaba
 */
public class CommonFrameA extends AppPage {
    
    /* 確認画面用のモーダル */
    /** モーダル確認画面で「処理実行」が選択されたときにTreuになるモデルオブジェクト*/
    final private Model<Boolean> doExecute = Model.of(false);
    final private ModalWindow modalCommonConfirm = new ModalWindow("modalCommonConfirm");
    
    /* [デバッグ用] メールに記載されたURLを表示するコンテナ */
    final private WebMarkupContainer cntDebugUrlOnMail = new WebMarkupContainer("cntDebugUrlOnMail");
    final private ExternalLink linkDebugUrlOnMail = new ExternalLink("debugUrlOnMail", ""){
        @Override
        public boolean isVisible() {
            return StringUtils.isEmpty(this.getDefaultModelObjectAsString()) == false;
        }
    };
    protected void addDebugUrl(String debugUrl){
        linkDebugUrlOnMail.setDefaultModelObject(debugUrl);
    }
    public CommonFrameA() {
        
        /* ロゴのクリック */
        //add(new BookmarkablePageLink<Void>("goTop", TopPage.class));
//        add(new ExternalLink("goTop",ResourceReader.getStringQuick("url.back.top")));
        
        /*
         * ログイン情報領域
         */
        WebMarkupContainer divLoginUser = new WebMarkupContainer("divLoginUser"){
            @Override
            public boolean isVisible() {
                //return AppSession.isLogin(); // ログイン中のみ表示する。
                return true;
            }
        };
        add(divLoginUser);
        
        /*
         * ログイン中ユーザ
         */
        Model<String> loginUserId = new Model<String>() {
            @Override
            public String getObject() {
                if(AppSession.get().isLogin()) {
                    String loginid = AppSession.get().getLoginUser().getLoginid();
                    //return "ログインユーザー：" + loginid;
                    return "ログインユーザー：" + StringUtils.abbreviate(loginid, 30);
                } else {
                    //return "ログインしていません";
                    return "";
                }
            }
        };
        Label labelLoginId = new Label("labelLoginId", loginUserId);
        divLoginUser.add(labelLoginId);
        
        /*
         * ログアウトボタン
         */
        Form<Void> formLoginUser = new Form<Void>("formLoginUser");
        divLoginUser.add(formLoginUser);
        Button buttonLogout = new Button("buttonLogout") {
            @Override
            public void onSubmit() {
                
                /* APIログアウト相当の実施 */
                logout.execute(AppSession.get().getLoginUser().getLoginid());
                
                /* セッション無効化 */
                AppSession.get().invalidateNow();
                
                /* トップ画面へ遷移 */
                //setResponsePage(getApplication().getHomePage());
            }
            @Override
            public boolean isVisible() {
                return AppSession.get().isLogin(); // ログイン中のみ表示する。
            }
        };
        formLoginUser.add(buttonLogout);
        
        /* 確認画面用のモーダル */
        /** モーダル確認画面で「処理実行」が選択されたときにTreuになるモデルオブジェクト*/
        add(modalCommonConfirm);
        
        /* デバッグ出力：メールに記載したURL */
        cntDebugUrlOnMail.setOutputMarkupId(true);
        add(cntDebugUrlOnMail);
        linkDebugUrlOnMail.setOutputMarkupId(true);
        linkDebugUrlOnMail.setOutputMarkupPlaceholderTag(true);
        cntDebugUrlOnMail.add(linkDebugUrlOnMail);
        
//        /*
//         * LocaleStringに関するデバッグ情報
//         */
//        WebMarkupContainer devls = new WebMarkupContainer("devls") {
//            @Override
//            public boolean isVisible() {
//                return AppLogger.isDebug();
//            }
//        };
//        add(devls);
        
//        Localestring cnd = new Localestring();
//        cnd.setScreenid(getScreenId());
//        List<Localestring> localestrings = localestringDao.get(cnd);
//        devls.add(new ListView<Localestring>("listView", localestrings) {
//            @Override
//            protected void populateItem(ListItem<Localestring> item) {
//                item.add(new Label("screenid", item.getModelObject().getScreenid()));
//                item.add(new Label("controlid", item.getModelObject().getControlid()));
//                item.add(new Label("lang", String.valueOf(item.getModelObject().getLanguageid())));
//                item.add(new Label("string", String.valueOf(item.getModelObject().getPrintstring())));
//            }
//        });
        
    }

    /** モーダル確認画面を呼び出すためのボタン（共通実装）*/
    protected abstract class ConfirmAjaxButton extends AjaxButton {
        public ConfirmAjaxButton(String id) {
            super(id);
        }
        @Override
        final protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
            
            /* 
             * 事前処理
             *  呼び出し元のPageクラスで実装したexecuteBeforeの処理を行います。
             */
            boolean check = executeBefore();
            if(check == false 
                    || hasInputError()) {
                
                FeedbackPanel feedback = (FeedbackPanel)getPage().get("feedback");
                if(feedback != null) {
                    target.add(feedback);
                }
                return; // 【処理中断】
            }
            
            doExecute.setObject(false);
            
            /* モーダル確認画面を構築 */
            //modalDefPreview.setTitle("");
            modalCommonConfirm.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
            final Integer MODAL_PREVIEW_HEIGHT = 150;
            final Integer MODAL_PREVIEW_WIDTH = 400;
            modalCommonConfirm.setInitialHeight(MODAL_PREVIEW_HEIGHT);
            modalCommonConfirm.setInitialWidth(MODAL_PREVIEW_WIDTH);
            modalCommonConfirm.setResizable(true);
            modalCommonConfirm.setPageCreator(new ModalWindow.PageCreator() {
                private static final long serialVersionUID = 1L;
                public Page createPage() {
                    /* Pageインスタンスの作成 */
                    CommonConfirmPage modalPage = new CommonConfirmPage();
                    /* 
                     * 確認メッセージの設定
                     * 　呼び出し元のPageクラスでオーバーライドして設定します。
                     */
                    modalPage.confirmMessage = getConfirmMessage();
                    modalPage.confirmMessageStrong = getConfirmMessageStrong();
                    /*
                     * executableオブジェクトの設定
                     * 　executableは確認モーダル画面の「実行」ボタンを押した直後に実行されます。
                     */
                    modalPage.executable = new CommonConfirmPage.Executable() {
                        @Override
                        void execute() {
                            executableWork();
                        }
                    };
                    
                    /* 
                     * CallBack の設定
                     *  Modal画面から呼び出し元のPageオブジェクトに参照を引き渡す処理です。
                     *  Callbackクラスを使用し、PageReferenceを経由しないと、正しく引き渡しできません。
                     */
                    final CommonConfirmPage.Callback callback = new CommonConfirmPage.Callback() {
                        @Override
                        public void callback(AjaxRequestTarget target) {
                            CommonFrameA me = (CommonFrameA)getPage().getPageReference().getPage(); // 左記の実装でないと、インスタンスが変化する。
                            me.doExecute.setObject(true);
                        }
                    };
                    modalPage.callback = callback;
                    return modalPage;
                }
            });
            /* CallBack の処理 */
            modalCommonConfirm.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
                private static final long serialVersionUID = 1L;
                @Override
                public void onClose(AjaxRequestTarget target) {
                    if(doExecute.getObject()) {
                        /* 確認モーダル画面の「実行」ボタンを押した後、呼び出し元のPageクラスで実行される処理。 */
                        executeAfter(target);
                        
                        FeedbackPanel feedback = (FeedbackPanel)getPage().get("feedback");
                        if(feedback != null) {
                            target.add(feedback);
                        }
                        
                        if(AppLogger.isDebug()) {
                            /* [デバッグ用] メールに記載されたURLを表示するコンテナ */
                            target.add(cntDebugUrlOnMail);
                        }
                    }
                }
            });
            modalCommonConfirm.show(target); // モーダルを表示
        }

        @Override
        protected void onError(AjaxRequestTarget target, Form<?> form) {
         // 処理なし
        }

        /** 確認メッセージの設定 */
        abstract String getConfirmMessage();
        /** 確認メッセージの設定 */
        String getConfirmMessageStrong(){
            return "";
        };
        /**
         * 前処理
         * 　入力値チェックを行います。
         * 　呼び出し元のPageクラスでオーバーライドします。
         * 　入力値チェックが不要の場合は、オーバーライドしなくてよいです。
         */
        boolean executeBefore() {
            return true;
        }
        /** 
         * 確認モーダル画面の「実行」ボタンを押した直後に実行される処理。
         * ここでは、呼び出し元のPageクラスのメンバに、正しく値を設定することができないことに注意する。
         */
        void executableWork(){
            // 必要に応じてオーバーライド
        };
        /**
         * 確認モーダル画面の「実行」ボタンを押した後、呼び出し元のPageクラスで実行される処理。
         */
        abstract void executeAfter(AjaxRequestTarget target);
    }
    
    protected void doパスワードリセット(final Integer targetUserid, PasswordTicketManager passwordTicketManager, String mailValue) {
        
        
        
        /* 共通機能：パスワード登録チケット発行 からチケットを取得する */
        String random = passwordTicketManager.executeパスワードリセット(targetUserid);
        
        /* パスワード再設定用メールを送信する */
        MailSetting setting = new MailSetting();
        setting.setTemplate(ResourceReader.getText("message/mail.resetpw"));
        setting.setMailTo(mailValue);
        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);
        }
    }
    
    private Page returnPage;
    protected Page getReturnPage() {
        return returnPage;
    }
    protected void setReturnPage(Page returnPage) {
        this.returnPage = returnPage;
    }
    
    
    
    /**
     * 共通戻るリンクの設置
     */
    protected void createCommonBackLinks() {
        add(new ExternalLink("lnkMember", ResourceReader.getStringQuick("url.back.member")) {
            @Override
            public boolean isVisible() {
                return isMember();
            }
        });
        add(new ExternalLink("lnkOrgAdmin", ResourceReader.getStringQuick("url.back.orgadmin")) {
            @Override
            public boolean isVisible() {
                return isOrgAdmin();
            }
        });
        add(new ExternalLink("lnkSysAdmin", ResourceReader.getStringQuick("url.back.sysadmin")) {
            @Override
            public boolean isVisible() {
                return isSystemAdmin();
            }
        });
    }
    /**
     * 画面固有の戻るボタンの設置
     * @param clz
     * @param string
     */
    protected void createBackLink(final Class<? extends CommonFrameA> clz, final String name) {
        Link<Void> linkReturn = new Link<Void>("lnkReturn") {
            @Override
            public void onClick() {
                setResponsePage(getReturnPage());
            }
            @Override
            public boolean isVisible() {
                return getReturnPage() != null;
            }
        };
        Label lnkReturnAnker = new Label("lnkReturnAnker", new Model<String>(){
            @Override
            public String getObject() {
                if(getReturnPage() != null  && getReturnPage().getClass().equals(clz)) {
                    return name + "へ戻る";
                } else {
                    return "前へ戻る";
                }
            }
        });
        linkReturn.add(lnkReturnAnker);
        add(linkReturn);
    }
    /**
     * フィードバックパネルの設置
     */
    protected void createFeedbackPanel() {
        final FeedbackPanel feedbackPanel = new FeedbackPanel("feedback");
        feedbackPanel.setOutputMarkupId(true);
        add(feedbackPanel);
    }
    
}
