/*
 * 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@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.venice.community;

import java.util.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.venice.iface.VeniceCategory;

class CategoryImpl implements VeniceCategory
{
  /*--------------------------------------------------------------------------------
   * Internal class for saving category segments
   *--------------------------------------------------------------------------------
   */

  private static class Segment
  {
    /*====================================================================
     * Attributes
     *====================================================================
     */

    private int id;         // ID of this category
    private String name;    // name of this segment

    /*====================================================================
     * Constructor
     *====================================================================
     */

    Segment(int id, String name)
    {
      this.id = id;
      this.name = name;

    } // end constructor

    /*====================================================================
     * Public getters
     *====================================================================
     */

    final int getID()
    {
      return id;

    } // end getID

    final String getName()
    {
      return name;

    } // end getName

  } // end class Segment

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private CategoryManager m_mgr;     // pointer to manager object
  private LinkedList m_cats;         // the actual category segments
  private int m_symlink = -1;        // if our category is actually a symlink

  /*--------------------------------------------------------------------------------
   * Constructors
   *--------------------------------------------------------------------------------
   */

  CategoryImpl(CategoryManager mgr)
  {
    m_mgr = mgr;
    m_cats = new LinkedList();

  } // end constructor

  CategoryImpl(CategoryManager mgr, int id, int symlink, String name)
  {
    m_mgr = mgr;
    m_cats = new LinkedList();
    m_symlink = symlink;
    m_cats.add(new Segment(id,name));

  } // end constructor

  CategoryImpl(CategoryImpl parent, int id, int symlink, String name)
  {
    m_mgr = parent.m_mgr;
    m_cats = (LinkedList)(parent.m_cats.clone());
    m_symlink = symlink;
    m_cats.add(new Segment(id,name));

  } // end constructor

  private CategoryImpl(CategoryImpl other, int copy_levels)
  {
    m_mgr = other.m_mgr;
    m_cats = new LinkedList();
    m_symlink = ((copy_levels==other.m_cats.size()) ? other.m_symlink : -1);
    Iterator it = other.m_cats.iterator();
    for (int i=0; i<copy_levels; i++)
      m_cats.add(it.next());

  } // end constructor

  /*--------------------------------------------------------------------------------
   * Implementations from interface VeniceCategory
   *--------------------------------------------------------------------------------
   */

  public int getCategoryID()
  {
    if (m_cats.size()>0)
      return ((Segment)(m_cats.getLast())).getID();
    else
      return -1;

  } // end getCategoryID

  public int getNumLevels()
  {
    return m_cats.size();

  } // end getNumLevels

  public int getIDAtLevel(int level)
  {
    return ((Segment)(m_cats.get(level))).getID();

  } // end getIDAtLevel

  public String getTitleAtLevel(int level)
  {
    return ((Segment)(m_cats.get(level))).getName();

  } // end getTitleAtLevel

  public List getSubCategories() throws DatabaseException
  {
    return m_mgr.getCategorySublist(this.getLinkedCategoryID());

  } // end getSubCategories

  public VeniceCategory getSuperCategory(int levels)
  {
    return m_mgr.canonicalize(new CategoryImpl(this,levels));

  } // end getSuperCategory

  public VeniceCategory getParentCategory()
  {
    return m_mgr.canonicalize(new CategoryImpl(this,m_cats.size()-1));

  } // end getParentCategoryID

  public int getLinkedCategoryID()
  {
    if (m_symlink>=0)
      return m_symlink;
    else
      return this.getCategoryID();

  } // end getLinkedCategoryID

  public boolean isSymbolicLink()
  {
    return (m_symlink>=0);

  } // end isSymbolicLink

  public VeniceCategory getLinkedCategory() throws DatabaseException
  {
    if (m_symlink<0)
      return this;
    return (VeniceCategory)(m_mgr.lookup(m_symlink));

  } // end getLinkedCategory

  public boolean equals(Object obj)
  {
    if (obj==null)
      return false;
    if (obj instanceof VeniceCategory)
      return (((VeniceCategory)obj).getLinkedCategoryID()==this.getLinkedCategoryID());
    return this.toString().equals(obj.toString());

  } // end equals

  public int hashCode()
  {
    return this.getLinkedCategoryID();

  } // end hashCode

  public String toString()
  {
    StringBuffer buf = new StringBuffer();
    Iterator it = m_cats.iterator();
    while (it.hasNext())
    { // concatenate all the parts together
      Segment seg = (Segment)(it.next());
      if (buf.length()>0)
	buf.append(": ");
      buf.append(seg.getName());

    } // end while

    return buf.toString();

  } // end toString

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

  void dispose()
  {
    m_mgr = null;
    m_cats.clear();
    m_cats = null;

  } // end dispose

} // end class CategoryImpl
