private void encodeTabHeader(
      FacesContext context,
      AbstractTab tab,
      ResponseWriter writer,
      AbstractTogglePanelTitledItem.HeaderStates state)
      throws IOException {

    String headerStateClass = "rf-tab-hdr-" + state.abbreviation();
    String headerPositionClass = "rf-tab-hdr-" + positionAbbreviation(tab);

    writer.startElement(TD_ELEM, tab);
    writer.writeAttribute(ID_ATTRIBUTE, tab.getClientId(context) + ":header", null);
    renderPassThroughAttributes(context, tab, HEADER_ATTRIBUTES);
    writer.writeAttribute(
        CLASS_ATTRIBUTE,
        concatClasses(
            "rf-tab-hdr",
            headerStateClass,
            headerPositionClass,
            attributeAsString(tab, "headerClass"),
            attributeAsString(tab, state.headerClass())),
        null);
    writer.writeAttribute(STYLE_ATTRIBUTE, attributeAsString(tab, "headerStyle"), null);
    writer.writeAttribute("data-tabname", tab.getName(), null);

    writer.startElement(SPAN_ELEM, tab);
    writer.writeAttribute(CLASS_ATTRIBUTE, "rf-tab-lbl", null);

    UIComponent headerFacet = tab.getHeaderFacet(state);
    if (headerFacet != null && headerFacet.isRendered()) {
      headerFacet.encodeAll(context);
    } else {
      Object headerText = tab.getAttributes().get("header");
      if (headerText != null && !headerText.equals("")) {
        writer.writeText(headerText, null);
      }
    }

    writer.endElement(SPAN_ELEM);

    writer.endElement(TD_ELEM);
  }