/*
 * Copyright (C) 2005-2011 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see .
 */
package org.alfresco.service.cmr.site;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults;
import org.alfresco.repo.node.getchildren.FilterProp;
import org.alfresco.repo.security.authority.UnknownAuthorityException;
import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
/**
 * Site service fundamental API.
 * 
 * This service API is designed to support the public facing Site APIs
 * 
 * @author Roy Wetherall
 */
public interface SiteService
{
    static String DOCUMENT_LIBRARY = "documentLibrary";
    
    /**
     * Create a new site.
     * 
     * @param sitePreset    site preset name
     * @param shortName     site short name, must be unique
     * @param title         site title
     * @param description   site description
     * @param isPublic      whether the site is public or not (true = public, false = private)
     * @return SiteInfo     information about the created site
     * @deprecated          since version 3.2, replaced by {@link #createSite(String, String, String, String, SiteVisibility)}
     */
    @Auditable(parameters = {"sitePreset", "shortName"})
    SiteInfo createSite(String sitePreset, String shortName, String title, String description, boolean isPublic);
    
    /**
     * Create a new site.
     * 
     * @param sitePreset    site preset name
     * @param shortName     site short name, must be unique
     * @param title         site title
     * @param description   site description
     * @param visibility    site visibility (public|moderated|private)
     * @return SiteInfo     information about the created site
     */
    @Auditable(parameters = {"sitePreset", "shortName"})
    SiteInfo createSite(String sitePreset, String shortName, String title, String description, SiteVisibility visibility);
    
    /**
     * Create a new site.
     * 
     * @param sitePreset    site preset name
     * @param shortName     site short name, must be unique
     * @param title         site title
     * @param description   site description
     * @param visibility    site visibility (public|moderated|private)
     * @param siteType	    type of site to create, must be a sub-type of st:site
     * @return SiteInfo     information about the created site
     */
    @Auditable(parameters = {"sitePreset", "shortName"})
    SiteInfo createSite(String sitePreset, String shortName, String title, String description, SiteVisibility visibility, QName siteType);
    
    /**
     * This method checks if the currently authenticated user has permission to create sites.
     * 
     * @return true if current user can create sites, else false.
     * @since 3.4
     */
    @NotAuditable
    boolean hasCreateSitePermissions();
    
    /**
     * This method will find all {@link SiteInfo sites} available to the currently authenticated user based on
     * the specified site filter, site preset filter and result set size.
     * The filter parameter will match any sites whose {@link ContentModel#PROP_NAME cm:name}, {@link ContentModel#PROP_TITLE cm:title}
     * or {@link ContentModel#PROP_DESCRIPTION cm:description} contain the specified string (ignoring case).
     * 
     * Note that this method uses Alfresco Full Text Search to retrieve results
     * and depending on server Lucene, SOLR configuration may only offer eventually consistent results.
     * 
     * @param filter Any supplied filter will be wrapped in asterisks (e.g. '*foo*') and used to match the sites' cm:name, cm:title or cm:description.
     * @param sitePresetFilter a site preset filter name to match against.
     * @param size this parameter specifies a maximum result set size.
     * @return Site objects for all matching sites up to the maximum result size.
     * 
     * @since 4.0
     */
    @NotAuditable
    List findSites(String filter, String sitePresetFilter, int size);
    
    /**
     * List the available sites.  This list can optionally be filtered by site name/title/description and/or site preset.
     * 
     * Note: Starting with Alfresco 4.0, the filter parameter will only match sites whose {@link ContentModel#PROP_NAME cm:name} or
     * {@link ContentModel#PROP_TITLE cm:title} or {@link ContentModel#PROP_DESCRIPTION cm:description} start with
     * the specified string (ignoring case). The listing of sites whose cm:names (or titles or descriptions) contain the
     * specified string is no longer supported. To retrieve sites whose cm:names etc contain a substring, {@link SiteService#findSites(String, String, int)}
     * should be used instead.
     * 
     * @param filter                filter (sites whose cm:name, cm:title or cm:description START WITH filter)
     * @param sitePresetFilter      site preset filter (sites whose preset EQUALS sitePresetFilter)
     * @param size                  list maximum size or zero for all
     * @return List       list of site information
     */
    @NotAuditable
    List listSites(String filter, String sitePresetFilter, int size);
    
    /**
     * List the available sites.  This list can optionally be filtered by site name/title/description and/or site preset.
     * 
     * Note: Starting with Alfresco 4.0, the filter parameter will only match sites whose {@link ContentModel#PROP_NAME cm:name} or
     * {@link ContentModel#PROP_TITLE cm:title} or {@link ContentModel#PROP_DESCRIPTION cm:description} start with
     * the specified string (ignoring case). The listing of sites whose cm:names (or titles or descriptions) contain the
     * specified string is no longer supported. To retrieve sites whose cm:names etc contain a substring, {@link SiteService#findSites(String, String, int)}
     * should be used instead.
     * 
     * @param filter                filter
     * @param sitePresetFilter      site preset filter
     * @return List       list of site information
     */
    @NotAuditable
    List listSites(String filter, String sitePresetFilter);
    
    /**
     * List all the sites that the specified user has a explicit membership to.
     *
     * @param userName          user name
     * @return List   list of site information
     */
    @NotAuditable
    List listSites(String userName);
    
    /**
     * This method returns {@link PagingResults paged result sets} of {@link SiteInfo} objects, which should be
     * more efficient than the unpaged methods also available on this interface. It is also guaranteed to return
     * fully consistent results.
     * 
     * @param filterProps property filters
     * @param sortProps sorting options
     * @param pagingRequest paging options
     * 
     * @return a page of SiteInfo objects.
     * @since 4.0
     */
    PagingResults listSites(List filterProps, List> sortProps, PagingRequest pagingRequest);
    
    /**
     * Gets site information based on the short name of a site.
     * 
     * Returns null if the site can not be found.
     * 
     * @param shortName     the site short name
     * @return SiteInfo     the site information
     */
    @NotAuditable
    SiteInfo getSite(String shortName);
    
    /**
     * This method gets the {@link SiteInfo} for the Share Site which contains the given NodeRef.
     * If the given NodeRef is not contained within a Share Site, then null is returned.
     * 
     * @param nodeRef   the node whose containing site's info is to be found.
     * @return SiteInfo  site information for the containing site or null if node is not in a site.
     */
    @NotAuditable
    SiteInfo getSite(NodeRef nodeRef);
    
    /**
     * Update the site information.
     * 
     * Note that the short name and site preset of a site can not be updated once the site has been created.
     * 
     * @param siteInfo  site information
     */
    @Auditable
    void updateSite(SiteInfo siteInfo);
    
    /**
     * Delete the site.
     * 
     * @param shortName     site short name
     */
    @Auditable(parameters = {"shortName"})
    void deleteSite(String shortName);
    
    /**
     * List the members of the site.  This includes both users and groups.
     * 
     * Name and role filters are optional and if not specified all the members of the site are returned.
     * 
     * @param shortName     site short name
     * @param nameFilter    name filter
     * @param roleFilter    role filter
     * @param size          max results size crop if >0
     * @return Map  the authority name and their role
     */
    @NotAuditable
    Map listMembers(String shortName, String nameFilter, String roleFilter, int size);
    
    /**
     * List the members of the site.  This includes both users and groups if collapseGroups is set to false, otherwise all
     * groups that are members are collapsed into their component users and listed.
     * 
     * @param shortName         site short name
     * @param nameFilter        name filter
     * @param roleFilter        role filter
     * @param size          max results size crop if >0
     * @param collapseGroups    true if collapse member groups into user list, false otherwise
     * @return Map  the authority name and their role
     */
    @NotAuditable
    Map listMembers(String shortName, String nameFilter, String roleFilter, int size, boolean collapseGroups);
    
    /**
     * Gets the role of the specified user.
     * 
     * @param shortName     site short name
     * @param authorityName full authority name (so if it's a group then its prefixed with 'GROUP_')
     * @return String       site role, null if none
     */
    @NotAuditable
    String getMembersRole(String shortName, String authorityName);
    
    /**
     * Indicates whether an authority is a member of a site or not
     * 
     * @param shortName     site short name
     * @param authorityName authority name (so if it's a group then its prefixed with 'GROUP_')
     * @return boolean      true if the authority is a member of the site, false otherwise
     */
    @NotAuditable
    boolean isMember(String shortName, String authorityName);
    
    /**
     * Sets the role of an authority within a site
     * 
     * @param shortName     site short name
     * @param authorityName authority name (so if it's a group then its prefixed with 'GROUP_')
     * @param role          site role
     * @throws UnknownAuthorityException if the site role is not supported.
     */
    @Auditable(parameters = {"shortName", "authorityName", "role"})
    void setMembership(String shortName, String authorityName, String role);
    
    /**
     * Clears an authorities role within a site
     * 
     * @param shortName     site short name
     * @param authorityName authority name (so if it's a group then its prefixed with 'GROUP_')
     */
    @Auditable(parameters = {"shortName", "authorityName"})
    void removeMembership(String shortName, String authorityName);
    
    /**
     * Creates a container for a component is a site of the given container type (must be a sub-type of st:siteContainer)
     * 
     * If no container type is specified then a node of type st:siteContainer is created.
     * 
     * The map of container properties are set on the created container node.  Null can be provided when no properties
     * need to be set.
     * 
     * @param shortName                 site short name
     * @param componentId               component id
     * @param containerType             container type to create (can be null)
     * @param containerProperties       container property values (can be null)
     * @return noderef of container or null if a container can't be created.
     */
    @NotAuditable
    NodeRef createContainer(String shortName, String componentId, QName containerType, Map containerProperties);
    
    /**
     * Gets the "container" folder for the specified
     * component.
     *
     * @param shortName  short name of site
     * @param componentId  component id
     * @param folderType  type of folder to create (if null, creates standard folder)
     * @return  noderef of container
     */
    @NotAuditable
    NodeRef getContainer(String shortName, String componentId);
    /**
     * Determines if a "container" folder for the specified component exists.
     * 
     * @param shortName  short name of site
     * @param componentId  component id
     * @return  true => "container" folder exists for component
     */
    @NotAuditable
    boolean hasContainer(String shortName, String componentId);
    
    /**
     * Gets a list of all the currently available roles that a user can perform on 
     *  all sites
     * 
     * @return  List    list of available roles
     */
    @NotAuditable
    List getSiteRoles();
     
    /**
     * Gets a list of all the currently available roles that a user can perform on 
     *  a specific site. This will generally only differ from {@link #getSiteRoles()}
     *  if your site is of a custom type.
     * 
     * @return  List    list of available roles
     */
    @NotAuditable
    List getSiteRoles(String shortName);
     
    /**
     * Gets the sites group.  All members of the site are contained within this group.
     * 
     * @param shortName     site short name
     * @return String       group name
     */
    @NotAuditable
    String getSiteGroup(String shortName);
    
    /**
     * Gets the sites role group.  All members assigned the given role will be members of 
     * the returned group.
     * 
     * @param shortName     site short name
     * @param role          membership role
     * @return String       group name
     */
    @NotAuditable
    String getSiteRoleGroup(String shortName, String role);
    
    /**
     * Gets the reference to the folder that is the Site root node.
     * 
     * @return site root node.
     */
    @NotAuditable
    NodeRef getSiteRoot();
    
    /**
     * This method cleans the permissions on the specified node. It is intended to be used after a
     * node is moved or copied from one site to another. Permissions relating to the former site are
     * removed and the node is given the default permissions for its new site.
     * 
     * @param relocatedNode
     * @param containingSite
     * @since 3.4.2
     */
    public void cleanSitePermissions(NodeRef relocatedNode, SiteInfo containingSite);
}