/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@ricochet.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2004 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.venice.ui.menus;

import java.io.*;
import java.util.*;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.ui.config.RootConfig;
import com.silverwrist.venice.util.XMLLoader;

public class MenuTemplate
{
  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private String m_identifier;     // menu template identifier
  private RootConfig m_rootconf;   // backreference to root configuration
  private Map m_blocks;            // blocks defined in menu template
  private String m_title_single;   // single title block
  private String m_title_double;   // double title block
  private Map m_items;             // item templates defined in menu template
  private Map m_links;             // link templates defined in menu template

  /*--------------------------------------------------------------------------------
   * Constructor
   *--------------------------------------------------------------------------------
   */

  public MenuTemplate(Element elt, RootConfig rootconf, String identifier) throws ConfigException
  {
    XMLLoader loader = XMLLoader.get();

    loader.configVerifyNodeName(elt,"menu-template");  // verify the name of the root node
    m_identifier = identifier;
    m_rootconf = rootconf;

    // load the contents of the menu template
    HashMap tmp_blocks = new HashMap();
    HashMap tmp_items = new HashMap();
    HashMap tmp_links = new HashMap();
    NodeList nl = elt.getChildNodes();
    for (int i=0; i<nl.getLength(); i++)
    { // examine each child node
      Node n = nl.item(i);
      if (n.getNodeType()==Node.ELEMENT_NODE)
      { // look at the node name
	Element ne = (Element)n;
	String nn = n.getNodeName();
	if (nn.equals("block"))
	{ // get block by ID and save it off
	  String id = ne.getAttribute("id");
	  if (StringUtil.isStringEmpty(id))
	    throw new ConfigException("menu template \"" + identifier + "\" has a <block/> with no id",ne);
	  DOMElementHelper h = new DOMElementHelper(ne);
	  tmp_blocks.put(id,h.getElementText());

	} // end if
	else if (nn.equals("title"))
	{ // get title type and save it off
	  String typ = ne.getAttribute("type");
	  if ((typ==null) || !(typ.equalsIgnoreCase("single") || typ.equalsIgnoreCase("double")))
	    throw new ConfigException("menu template \"" + identifier + "\" has a <title/> with bad type \""
				      + typ + "\"",ne);
	  DOMElementHelper h = new DOMElementHelper(ne);
	  if (typ.equalsIgnoreCase("single"))
	    m_title_single = h.getElementText();
	  else
	    m_title_double = h.getElementText();

	} // end else if
	else if (nn.equals("item"))
	{ // save off item template
	  String typ = ne.getAttribute("type");
	  if (StringUtil.isStringEmpty(typ))
	    throw new ConfigException("menu template \"" + identifier + "\" has an <item/> with no type",ne);
	  DOMElementHelper h = new DOMElementHelper(ne);
	  tmp_items.put(typ,h.getElementText());
	  
	} // end else if
	else if (nn.equals("link"))
	{ // save off the link template
	  String typ = ne.getAttribute("type");
	  if (StringUtil.isStringEmpty(typ))
	    throw new ConfigException("menu template \"" + identifier + "\" has a <link/> with no type",ne);
	  DOMElementHelper h = new DOMElementHelper(ne);
	  tmp_links.put(typ,h.getElementText());

	} // end else if
	else  // unknown item
	  throw new ConfigException("unknown element <" + nn + "/> inside <menu-template/>",ne);

      } // end if (element found)
      // else ignore this node

    } // end for

    if (tmp_blocks.isEmpty())
      m_blocks = Collections.EMPTY_MAP;
    else
      m_blocks = Collections.unmodifiableMap(tmp_blocks);
    if (tmp_items.isEmpty())
      m_items = Collections.EMPTY_MAP;
    else
      m_items = Collections.unmodifiableMap(tmp_items);
    if (tmp_links.isEmpty())
      m_links = Collections.EMPTY_MAP;
    else
      m_links = Collections.unmodifiableMap(tmp_links);

  } // end constructor

  /*--------------------------------------------------------------------------------
   * External operations
   *--------------------------------------------------------------------------------
   */

  public String getIdentifier()
  {
    return m_identifier;

  } // end getIdentifier

  public String getBlock(String id)
  {
    String bk = (String)(m_blocks.get(id));
    if (StringUtil.isStringEmpty(bk))
      return "";
    HashMap parms = new HashMap();
    m_rootconf.addFormatParams(parms);
    String rc = StringUtil.replaceAllVariables(bk,parms);
    return (rc==null) ? "" : rc;

  } // end getBlock

  public void writeBlock(Writer wr, String id) throws IOException
  {
    String bk = (String)(m_blocks.get(id));
    if (StringUtil.isStringEmpty(bk))
      return;

    HashMap parms = new HashMap();
    m_rootconf.addFormatParams(parms);
    String out = StringUtil.replaceAllVariables(bk,parms);
    if (!(StringUtil.isStringEmpty(out)))
      wr.write(out);

  } // end writeBlock

  public void renderTitle(Writer wr, String title, String subtitle) throws IOException
  {
    if (StringUtil.isStringEmpty(title))
      throw new IllegalArgumentException("title should not be empty!");
    String templ = m_title_single;
    HashMap parms = new HashMap();
    parms.put("title",StringUtil.encodeHTML(title));
    if (!(StringUtil.isStringEmpty(subtitle)))
    { // shift to "double" template
      templ = m_title_double;
      parms.put("subtitle",StringUtil.encodeHTML(subtitle));

    } // end if

    m_rootconf.addFormatParams(parms);
    String out = StringUtil.replaceAllVariables(templ,parms);
    if (!(StringUtil.isStringEmpty(out)))
      wr.write(out);

  } // end renderTitle

  public void renderItem(Writer wr, String type, String text, String link, Map params) throws IOException
  {
    String out = text;
    HashMap myparms = new HashMap();
    String templ = (String)(m_items.get(type));
    if (templ==null)
      templ = (String)(m_items.get("*"));
    if (templ!=null)
    { // format the item template
      if (text!=null)
      { // format the text
	m_rootconf.addFormatParams(myparms);
	myparms.putAll(params);
	myparms.put("text",text);
	out = StringUtil.replaceAllVariables(templ,myparms);

      } // end if
      else  // just use the template as the output text
	out = templ;

    } // end if

    if (link!=null)
    { // there's a link - need to look for a link template
      templ = (String)(m_links.get(type));
      if (templ==null)
	templ = (String)(m_links.get("*"));
      if (templ!=null)
      { // format the link
	myparms.clear();
	m_rootconf.addFormatParams(myparms);
	myparms.putAll(params);
	myparms.put("link",link);
	myparms.put("item",out);
	if (text!=null)
	  myparms.put("text",text);
	out = StringUtil.replaceAllVariables(templ,myparms);

      } // end if

    } // end if

    if (!(StringUtil.isStringEmpty(out)))
      wr.write(out);  // write it!

  } // end renderItem

  public void renderItem(Writer wr, String type, String text, String link) throws IOException
  {
    this.renderItem(wr,type,text,link,Collections.EMPTY_MAP);

  } // end renderItem

} // end class MenuTemplate
