public byte[] Bld(Xowe_wiki cur_wiki, Xoae_page page, Xow_popup_itm popup_itm, Bry_bfr wrdx_bfr) {
   if (output_js_clean) cur_wiki.Html_mgr().Js_cleaner().Clean_bfr(wiki, page.Ttl(), wrdx_bfr, 0);
   if (output_tidy)
     cur_wiki.Html_mgr().Tidy_mgr().Exec_tidy(wrdx_bfr, Bool_.Y, page.Url_bry_safe());
   byte[] hdom_bry = wrdx_bfr.To_bry_and_clear();
   String page_url =
       wrdx_bfr.Add(page.Wiki().Domain_bry())
           .Add(gplx.xowa.htmls.hrefs.Xoh_href_.Bry__wiki)
           .Add(
               gplx.langs.htmls.encoders.Gfo_url_encoder_.Href.Encode(
                   page.Ttl()
                       .Full_db())) // NOTE: was page.Url().Raw(), but that doesn't work for
                                    // Special:Search; PAGE:en.w:Earth and "Quotations";
                                    // DATE:2014-06-29
           .To_str_and_clear();
   fmtr_popup.Bld_bfr_many(
       wrdx_bfr,
       hdom_bry,
       wiki.Lang().Dir_ltr_bry(),
       page_url,
       String_.new_u8(page.Ttl().Full_txt_w_ttl_case()),
       popup_itm.Popup_id(),
       Xow_popup_html_bldr_.Bld_fmtr_wiki(
           fmtr_wiki,
           wrdx_bfr,
           cur_wiki.Domain_bry(),
           page.Wiki().Domain_bry()) // NOTE: use cur_wiki, not page_wiki; DATE:2014-06-28
       ,
       gplx.core.ios.Io_size_.To_str(page.Db().Text().Text_bry().length),
       page.Db().Page().Modified_on().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss(),
       Xow_popup_html_bldr_.Bld_fmtr_viewed(fmtr_viewed, app, wiki, wrdx_bfr, page.Ttl()),
       app.Fsys_mgr().Root_dir().To_http_file_bry());
   return wrdx_bfr.To_bry_and_clear();
 }
 public static byte[] Bld_fmtr_viewed(
     Bry_fmtr fmtr, Xoae_app app, Xowe_wiki wiki, Bry_bfr wrdx_bfr, Xoa_ttl ttl) {
   byte[] view_time_item = Bry_.Empty;
   gplx.xowa.users.history.Xou_history_itm history_itm =
       app.Usere().History_mgr().Get_or_null(wiki.Domain_bry(), ttl.Full_txt_w_ttl_case());
   if (history_itm != null)
     view_time_item =
         fmtr.Bld_bry_many(wrdx_bfr, history_itm.View_end().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss());
   return view_time_item;
 }
class Wdata_fmtr__json implements gplx.core.brys.Bfr_arg {
  private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
  private Xoapi_toggle_itm toggle_itm;
  private Wdata_toc_data toc_data;
  private Json_doc jdoc;

  public void Init_by_ctor(Wdata_toc_data toc_data, Xoapi_toggle_mgr toggle_mgr) {
    this.toc_data = toc_data.Itms_len_enable_n_();
    this.toggle_itm =
        toggle_mgr.Get_or_new("wikidatawiki-json")
            .Html_toggle_hdr_cls_(Bry_.new_a7("overflow:auto;"));
  }

  public void Init_by_lang(Wdata_hwtr_msgs msgs) {
    toc_data.Orig_(msgs.Json_div_hdr());
    toggle_itm.Init_msgs(msgs.Toggle_title_y(), msgs.Toggle_title_n());
  }

  public void Init_by_wdoc(Json_doc jdoc) {
    this.jdoc = jdoc;
    toc_data.Make(0);
  }

  public void Bfr_arg__add(Bry_bfr bfr) {
    if (jdoc == null) return; // TEST: wdoc doesn't have jdoc
    jdoc.Root_nde().Print_as_json(tmp_bfr, 0);
    fmtr.Bld_bfr_many(
        bfr,
        toc_data.Href(),
        toc_data.Text(),
        toggle_itm.Html_toggle_btn(),
        toggle_itm.Html_toggle_hdr(),
        tmp_bfr.To_bry_and_clear());
  }

  private final Bry_fmtr fmtr =
      Bry_fmtr.new_(
          String_.Concat_lines_nl_skip_last(
              "",
              "  <h2 class='wb-section-heading' id='~{hdr_href}'>~{hdr_text}~{toggle_btn}</h2>",
              "  <div class='visualClear'></div>",
              "  <pre~{toggle_hdr}>~{json}",
              "  </pre>",
              "  </div>"),
          "hdr_href",
          "hdr_text",
          "toggle_btn",
          "toggle_hdr",
          "json");
}
  private void Write_page_by_tid(
      Xop_ctx ctx,
      Xoh_wtr_ctx hctx,
      byte html_gen_tid,
      Bry_bfr bfr,
      Bry_fmtr fmtr,
      byte[] page_data) {
    // if custom_html, use it and exit; needed for Default_tab
    byte[] custom_html = page.Html_data().Custom_html();
    if (custom_html != null) {
      bfr.Add(custom_html);
      return;
    }
    // temp variables
    if (root_dir_bry == null) this.root_dir_bry = app.Fsys_mgr().Root_dir().To_http_file_bry();
    Xoa_ttl page_ttl = page.Ttl();
    int page_ns_id = page_ttl.Ns().Id();
    byte page_tid = Xow_page_tid.Identify(wiki.Domain_tid(), page_ns_id, page_ttl.Page_db());
    DateAdp modified_on = page.Db().Page().Modified_on();
    byte[] modified_on_msg =
        wiki.Msg_mgr()
            .Val_by_id_args(
                Xol_msg_itm_.Id_portal_lastmodified,
                modified_on.XtoStr_fmt_yyyy_MM_dd(),
                modified_on.XtoStr_fmt_HHmm());
    byte[] page_body_class = Xoh_page_body_cls.Calc(tmp_bfr, page_ttl, page_tid);
    byte[] html_content_editable =
        wiki.Gui_mgr().Cfg_browser().Content_editable() ? Content_editable_bry : Bry_.Empty;
    byte[] page_content_sub = Xoh_page_wtr_wkr_.Bld_page_content_sub(app, wiki, page, tmp_bfr);
    byte[] js_edit_toolbar_bry =
        html_gen_tid == Xopg_page_.Tid_edit
            ? wiki.Fragment_mgr().Html_js_edit_toolbar()
            : Bry_.Empty;
    Xol_vnt_mgr vnt_mgr = wiki.Lang().Vnt_mgr();
    if (vnt_mgr.Enabled()) {
      byte[] converted_title = vnt_mgr.Convert_lang().Converted_title(); // prefer converted title
      if (converted_title
          == null) // converted title does not exist; use regular page title and convert it
      converted_title = vnt_mgr.Convert_lang().Auto_convert(vnt_mgr.Cur_itm(), page_ttl.Page_txt());
      page_ttl = Xoa_ttl.Parse(wiki, page_ttl.Ns().Id(), converted_title);
    }
    byte[] page_name =
        Xoh_page_wtr_wkr_.Bld_page_name(
            tmp_bfr, page_ttl,
            null); // NOTE: page_name does not show display_title (<i>). always pass in null
    byte[] page_display_title =
        Xoh_page_wtr_wkr_.Bld_page_name(tmp_bfr, page_ttl, page.Html_data().Display_ttl());
    page.Html_data()
        .Custom_tab_name_(
            page_name); // set tab_name to page_name; note that if null, gui code will ignore and
                        // use Ttl.Page_txt; PAGE: zh.w:釣魚臺列嶼主權問題 DATE:2015-10-05
    Xow_portal_mgr portal_mgr = wiki.Html_mgr().Portal_mgr().Init_assert();
    fmtr.Bld_bfr_many(
        bfr,
        root_dir_bry,
        Xoa_app_.Version,
        Xoa_app_.Build_date,
        app.Tcp_server().Running_str(),
        page.Db().Page().Id(),
        page.Ttl().Full_db(),
        page_name,
        page.Html_data().Page_heading().Init(page.Html_data(), page_display_title),
        modified_on_msg,
        mgr.Css_common_bry(),
        mgr.Css_wiki_bry(),
        page.Html_data().Head_mgr().Init(app, wiki, page).Init_dflts(),
        page.Lang().Dir_ltr_bry(),
        page.Html_data().Indicators(),
        page_content_sub,
        wiki.Html_mgr().Portal_mgr().Div_jump_to(),
        wiki.Xtn_mgr().Xtn_pgbnr().Write_html(page, ctx, hctx),
        page_body_class,
        html_content_editable,
        page_data,
        wdata_lang_wtr

        // sidebar divs
        ,
        portal_mgr.Div_personal_bry(),
        portal_mgr.Div_ns_bry(wiki.Utl__bfr_mkr(), page_ttl, wiki.Ns_mgr()),
        portal_mgr.Div_view_bry(
            wiki.Utl__bfr_mkr(), html_gen_tid, page.Html_data().Xtn_search_text()),
        portal_mgr.Div_logo_bry(),
        portal_mgr.Div_home_bry(),
        new Xopg_xtn_skin_fmtr_arg(page, Xopg_xtn_skin_itm_tid.Tid_sidebar),
        portal_mgr.Div_sync_bry(
            tmp_bfr, app.Api_root().Addon().Bldr().Sync().Manual_enabled(), wiki, page),
        portal_mgr.Div_wikis_bry(wiki.Utl__bfr_mkr()),
        portal_mgr.Sidebar_mgr().Html_bry(),
        mgr.Edit_rename_div_bry(page_ttl),
        page.Html_data().Edit_preview_w_dbg(),
        js_edit_toolbar_bry);
    Xoh_page_wtr_wkr_.Bld_head_end(bfr, tmp_bfr, page); // add after </head>
    Xoh_page_wtr_wkr_.Bld_html_end(bfr, tmp_bfr, page); // add after </html>		
  }
public class Xol_duration_mgr {
  private Xol_msg_itm[] interval_msgs = null;
  private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
  private final Bry_fmtr tmp_fmtr = Bry_fmtr.New__tmp();

  public Xol_duration_mgr(Xol_lang_itm lang) {
    this.lang = lang;
  }

  private Xol_lang_itm lang;

  public Xol_interval_itm[] Get_duration_intervals(long seconds, Xol_duration_itm[] intervals) {
    if (intervals == null) intervals = Xol_duration_itm_.Ary_default;
    Array_.Sort(intervals, Xol_duration_itm_sorter.Instance);
    int intervals_len = intervals.length;
    long val = seconds;
    List_adp rv = List_adp_.New();
    for (int i = 0; i < intervals_len; i++) {
      Xol_duration_itm itm = intervals[i];
      long itm_seconds = itm.Seconds();
      val = seconds / itm_seconds;
      if (val > 0
          || (i == intervals_len - 1
              && rv.Count()
                  == 0) // always add one seg; EX: 40 seconds, but minutes requested -> 0 minutes;
                        // DATE:2014-05-10
      ) {
        seconds -= val * itm_seconds;
        rv.Add(new Xol_interval_itm(itm, val));
      }
    }
    return (Xol_interval_itm[]) rv.To_ary(Xol_interval_itm.class);
  }

  public byte[] Format_durations(Xop_ctx ctx, long seconds, Xol_duration_itm[] ary) {
    if (interval_msgs == null) Format_durations_init();
    Xol_interval_itm[] intervals = Get_duration_intervals(seconds, ary);
    int intervals_len = intervals.length;
    byte[][] msgs_ary = new byte[intervals_len][];
    for (int i = 0; i < intervals_len; i++) {
      Xol_interval_itm interval = intervals[i];
      Xol_msg_itm msg_itm = interval_msgs[interval.Duration_itm().Tid()];
      byte[] msg_bry = msg_itm.Fmt(tmp_bfr, tmp_fmtr, interval.Val());
      msg_bry = ctx.Wiki().Parser_mgr().Main().Parse_text_to_html(ctx, msg_bry);
      msgs_ary[i] = msg_bry;
    }
    return List_to_str(msgs_ary);
  }

  private byte[] Msg_and, Msg_word_separator, Msg_comma_separator;

  private void Format_durations_init() {
    Xol_msg_mgr msg_mgr = lang.Msg_mgr();
    int len = Xol_duration_itm_.Ary_default.length;
    interval_msgs = new Xol_msg_itm[len];
    for (int i = 0; i < len; i++) {
      Xol_duration_itm itm = Xol_duration_itm_.Ary_default[i];
      byte[] msg_key = Bry_.Add(Bry_duration, itm.Name_bry());
      interval_msgs[i] = msg_mgr.Itm_by_key_or_new(msg_key);
    }
  }

  private static final byte[] Bry_duration = Bry_.new_a7("duration-");

  private void List_to_str_init() {
    Xol_msg_mgr msg_mgr = lang.Msg_mgr();
    Msg_and = msg_mgr.Val_by_str_or_empty("and");
    Msg_word_separator = msg_mgr.Val_by_str_or_empty("word-separator");
    Msg_comma_separator = msg_mgr.Val_by_str_or_empty("comma-separator");
  }

  public byte[] List_to_str(byte[][] segs_ary) {
    int len = segs_ary.length;
    switch (len) {
      case 0:
        return Bry_.Empty;
      case 1:
        return segs_ary[0];
      default:
        if (Msg_and == null) List_to_str_init();
        int last_idx = len - 1;
        for (int i = 0; i < last_idx; i++) {
          if (i != 0) tmp_bfr.Add(Msg_comma_separator);
          tmp_bfr.Add(segs_ary[i]);
        }
        tmp_bfr.Add(Msg_and).Add(Msg_word_separator).Add(segs_ary[last_idx]);
        return tmp_bfr.To_bry_and_clear();
    }
  }
}
 public static byte[] Bld_fmtr_wiki(
     Bry_fmtr fmtr, Bry_bfr wrdx_bfr, byte[] wiki_domain, byte[] page_domain) {
   return Bry_.Eq(wiki_domain, page_domain)
       ? Bry_.Empty // same domain; return "";
       : fmtr.Bld_bry_many(wrdx_bfr, page_domain);
 }
public class Xow_popup_html_mkr {
  private Xoae_app app;
  private Xowe_wiki wiki;

  public Bry_fmtr Fmtr_popup() {
    return fmtr_popup;
  }

  private Bry_fmtr fmtr_popup = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_popup_keys);

  public Bry_fmtr Fmtr_viewed() {
    return fmtr_viewed;
  }

  private Bry_fmtr fmtr_viewed = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_viewed_keys);

  public Bry_fmtr Fmtr_wiki() {
    return fmtr_wiki;
  }

  private Bry_fmtr fmtr_wiki = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_wiki_keys);

  public Bry_fmtr Fmtr_next_sect() {
    return fmtr_next_sect;
  }

  private Bry_fmtr fmtr_next_sect = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_next_sect_keys);

  public void Output_js_clean_(boolean v) {
    output_js_clean = v;
  }

  private boolean output_js_clean = true;

  public void Output_tidy_(boolean v) {
    output_tidy = v;
  }

  private boolean output_tidy = true;

  public void Ctor(Xoae_app app, Xowe_wiki wiki) {
    this.wiki = wiki;
    this.app = app;
    wiki.Eval_mgr().Eval_mgr_(fmtr_popup, fmtr_viewed, fmtr_wiki, fmtr_next_sect);
  }

  public byte[] Bld(Xowe_wiki cur_wiki, Xoae_page page, Xow_popup_itm popup_itm, Bry_bfr wrdx_bfr) {
    if (output_js_clean) cur_wiki.Html_mgr().Js_cleaner().Clean_bfr(wiki, page.Ttl(), wrdx_bfr, 0);
    if (output_tidy)
      cur_wiki.Html_mgr().Tidy_mgr().Exec_tidy(wrdx_bfr, Bool_.Y, page.Url_bry_safe());
    byte[] hdom_bry = wrdx_bfr.To_bry_and_clear();
    String page_url =
        wrdx_bfr.Add(page.Wiki().Domain_bry())
            .Add(gplx.xowa.htmls.hrefs.Xoh_href_.Bry__wiki)
            .Add(
                gplx.langs.htmls.encoders.Gfo_url_encoder_.Href.Encode(
                    page.Ttl()
                        .Full_db())) // NOTE: was page.Url().Raw(), but that doesn't work for
                                     // Special:Search; PAGE:en.w:Earth and "Quotations";
                                     // DATE:2014-06-29
            .To_str_and_clear();
    fmtr_popup.Bld_bfr_many(
        wrdx_bfr,
        hdom_bry,
        wiki.Lang().Dir_ltr_bry(),
        page_url,
        String_.new_u8(page.Ttl().Full_txt_w_ttl_case()),
        popup_itm.Popup_id(),
        Xow_popup_html_bldr_.Bld_fmtr_wiki(
            fmtr_wiki,
            wrdx_bfr,
            cur_wiki.Domain_bry(),
            page.Wiki().Domain_bry()) // NOTE: use cur_wiki, not page_wiki; DATE:2014-06-28
        ,
        gplx.core.ios.Io_size_.To_str(page.Db().Text().Text_bry().length),
        page.Db().Page().Modified_on().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss(),
        Xow_popup_html_bldr_.Bld_fmtr_viewed(fmtr_viewed, app, wiki, wrdx_bfr, page.Ttl()),
        app.Fsys_mgr().Root_dir().To_http_file_bry());
    return wrdx_bfr.To_bry_and_clear();
  }
}