/*******************************************************************************
 * Copyright (C) 2004-2006 Intel Corp. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  - Neither the name of Intel Corp. nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

/**
 * @author Liang Hou, Intel Corp.
 */

#include "u/libu.h"
#include "wsman-xml.h"
#include "wsman-names.h"
#include "wsman-filter.h"

filter_t * filter_initialize(void)
{
	filter_t *filter = u_zalloc(sizeof(filter_t));
	return filter;
}


static int filter_set(filter_t *filter, const char *dialect, const char *query, epr_t *epr, hash_t *selectors,
	const int assocType, const char *assocClass, const char *resultClass, const char *role,
	const char *resultRole, char **resultProp, const int propNum)
{
	int i = 0;

	if(dialect == NULL) {
		filter->dialect = u_strdup(WSM_XPATH_FILTER_DIALECT);
	} else {
		filter->dialect = u_strdup(dialect);
	}

	if (query) {
		filter->query = u_strdup(query);
	} else if(epr != 0) {
		filter->epr = epr_copy(epr);
		filter->assocType = assocType;
		if(assocClass)
			filter->assocClass = u_strdup(assocClass);
		if(resultClass)
			filter->resultClass = u_strdup(resultClass);
		if(role)
			filter->role = u_strdup(role);
		if(resultRole)
			filter->resultRole = u_strdup(resultRole);
		if(resultProp && propNum) {
			filter->resultProp = u_malloc(propNum*sizeof(char *));
			if (filter->resultProp) {
				filter->PropNum = propNum;
				while (i < propNum) {
					filter->resultProp[i] = u_strdup(resultProp[i]);
					i++;
				}
			} else {
				filter->PropNum = 0;
			}
		}
	} else if(selectors) {
		hnode_t        *hn;
		hscan_t         hs;
                key_value_t *p;
		key_value_t *entry;
		filter->selectorset.count = hash_count(selectors);
                filter->selectorset.selectors = u_malloc(sizeof(key_value_t)*
			filter->selectorset.count);

		p = filter->selectorset.selectors;
		hash_scan_begin(&hs, selectors);
		while ((hn = hash_scan_next(&hs))) {
                  entry = (key_value_t *)hnode_get(hn);
                  key_value_create((char *)hnode_getkey(hn),
                                   (entry->type == 0)?entry->v.text:NULL,
                                   (entry->type == 1)?entry->v.epr:NULL, p);
			p++;
		}
	}
	else
		goto cleanup;
	return 0;
cleanup:
	return 1;
}

filter_t *filter_create(const char *dialect, const char *query, epr_t *epr, hash_t *selectors,
	const int assocType, const char *assocClass, const char *resultClass, const char *role,
	const char *resultRole, char **resultProp, const int propNum)
{
	int ret = 0;
	filter_t *filter = filter_initialize();
	if (filter == NULL)
		return NULL;
	ret = filter_set(filter, dialect, query, epr, selectors,
		    assocType, assocClass, resultClass, role, resultRole, resultProp, propNum);
	if (ret == 1 ) {
		filter_destroy(filter);
		return NULL;
	} else {
		return filter;
	}
}

int filter_set_simple(filter_t *filter, const char *dialect, const char *query)
{
	return filter_set(filter, dialect, query, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0);
}

filter_t * filter_create_simple(const char *dialect, const char *query)
{
	return filter_create(dialect, query, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0);
}

int filter_set_assoc(filter_t *filter, epr_t *epr, const int assocType, const char *assocClass,
	const char *resultClass, const char *role, const char *resultRole, char **resultProp,
	const int propNum)
{
	return filter_set(filter, WSM_ASSOCIATION_FILTER_DIALECT, NULL, epr, NULL, assocType,
		assocClass, resultClass, role, resultRole, resultProp, propNum);
}


filter_t * filter_create_assoc(epr_t *epr, const int assocType, const char *assocClass,
	const char *resultClass, const char *role, const char *resultRole, char **resultProp,
	const int propNum)
{
	return filter_create(WSM_ASSOCIATION_FILTER_DIALECT, NULL, epr, NULL, assocType,
		assocClass, resultClass, role, resultRole, resultProp, propNum);
}

filter_t * filter_create_selector(hash_t *selectors)
{
	return filter_create(WSM_SELECTOR_FILTER_DIALECT, NULL, NULL, selectors, 0,
		NULL, NULL, NULL, NULL, NULL, 0);
}

static int
_filter_add_selector(filter_t *filter, const char* key, const char *value, const epr_t *epr)
{
        key_value_t *entry;
        unsigned int i;
	if(filter == NULL || key == NULL || ((value == NULL) && (epr == NULL)))
		return 0;
	entry = filter->selectorset.selectors;
	for(i = 0; i < filter->selectorset.count; i++) {
		if(strcmp(key, entry[i].key) == 0)
			return -1;
	}
	entry = u_realloc(entry, (filter->selectorset.count+1) * sizeof(key_value_t));
	if(entry == NULL) return -1;
        key_value_create(key, value, epr, &(entry[filter->selectorset.count]));
	filter->selectorset.selectors = entry;
	filter->selectorset.count++;

	return 0;

}

int filter_add_selector(filter_t *filter, const char* key, const char *value)
{
  return _filter_add_selector(filter, key, value, NULL);
}

int filter_add_selector_epr(filter_t *filter, const char* key, const epr_t *value)
{
  return _filter_add_selector(filter, key, NULL, value);
}

filter_t * filter_copy(filter_t *filter)
{
	filter_t *filter_cpy = NULL;
	key_value_t *p1;
        key_value_t *p2;
	unsigned int i = 0;
	if(filter == NULL)
		return NULL;
	filter_cpy = u_zalloc(sizeof(filter_t));
	if(filter_cpy == NULL)
		return NULL;

	if(filter->dialect)
		filter_cpy->dialect = u_strdup(filter->dialect);
	filter_cpy->assocType = filter->assocType;
	if(filter->epr)
		filter_cpy->epr = epr_copy(filter->epr);
	if(filter->query)
		filter_cpy->query = u_strdup(filter->query);

	filter_cpy->selectorset.count = filter->selectorset.count;
	filter_cpy->selectorset.selectors = u_malloc(sizeof(key_value_t) *
		filter->selectorset.count);
	if (filter_cpy->selectorset.selectors) {
		p1 = filter->selectorset.selectors;
		p2 = filter_cpy->selectorset.selectors;
		for (i = 0; i < filter_cpy->selectorset.count; i++) {
			key_value_copy(p1, p2);
			p1++;
			p2++;
		}
	}

	if(filter->assocClass)
		filter_cpy->assocClass = u_strdup(filter->assocClass);
	if(filter->resultClass)
		filter_cpy->resultClass = u_strdup(filter->resultClass);
	if(filter->resultRole)
		filter_cpy->resultRole = u_strdup(filter->resultRole);
	if(filter->resultProp) {
		int i = 0;
		filter_cpy->resultProp = u_malloc(filter->PropNum*sizeof(char *));
		if (filter_cpy->resultProp != NULL) {
			filter_cpy->PropNum = filter->PropNum;
			while (i < filter->PropNum) {
				filter_cpy->resultProp[i] = u_strdup(filter->resultProp[i]);
				i++;
			}
		}
	}
	return filter_cpy;
}

void filter_destroy(filter_t *filter)
{
	key_value_t *p;
	unsigned int i;
	if(filter == NULL)
		return;
	if(filter->assocClass)
		u_free(filter->assocClass);
	if(filter->dialect)
		u_free(filter->dialect);
	if(filter->query)
		u_free(filter->query);
	if(filter->epr)
		epr_destroy(filter->epr);

	p = filter->selectorset.selectors;
	for(i = 0; i< filter->selectorset.count; i++) {
          key_value_destroy(p, 1);
		p++;
	}
	u_free(filter->selectorset.selectors);

	if(filter->resultClass)
		u_free(filter->resultClass);
	if(filter->resultProp) {
		int i = 0;
		while(i < filter->PropNum) {
			u_free(filter->resultProp[i]);
			i++;
		}
		u_free(filter->resultProp);
	}
	if(filter->resultRole)
		u_free(filter->resultRole);
	if(filter->role)
		u_free(filter->role);
	u_free(filter);
}

int filter_serialize(WsXmlNodeH node, filter_t *filter, const char *ns)
{
	int r = 0;
	WsXmlNodeH filter_node = NULL;
	WsXmlNodeH instance_node = NULL;
	if(filter->query) {
		filter_node = ws_xml_add_child(node, ns, WSM_FILTER, filter->query);
	} else if(filter->epr) {
		filter_node = ws_xml_add_child(node, ns, WSM_FILTER, NULL);
		if (!filter_node)
			return -1;
		if(filter->assocType == 0)
			instance_node = ws_xml_add_child(filter_node, XML_NS_CIM_BINDING, WSMB_ASSOCIATED_INSTANCES, NULL);
		else
			instance_node = ws_xml_add_child(filter_node, XML_NS_CIM_BINDING, WSMB_ASSOCIATION_INSTANCES, NULL);
		if (!instance_node)
			return -1;

		r = epr_serialize(instance_node, XML_NS_CIM_BINDING, WSMB_OBJECT, filter->epr, 1);

		if(r)
			return r;
		if(filter->assocClass)
			ws_xml_add_child(instance_node, XML_NS_CIM_BINDING, WSMB_ASSOCIATION_CLASS_NAME,
			filter->assocClass);
		if(filter->role)
			ws_xml_add_child(instance_node, XML_NS_CIM_BINDING, WSMB_ROLE, filter->role);
		if(filter->resultClass)
			ws_xml_add_child(instance_node, XML_NS_CIM_BINDING, WSMB_RESULT_CLASS_NAME,
			filter->resultClass);
		if(filter->resultRole)
			ws_xml_add_child(instance_node, XML_NS_CIM_BINDING, WSMB_RESULT_ROLE, filter->resultRole);
		if(filter->resultProp) {
			int i = 0;
			while(i < filter->PropNum) {
				ws_xml_add_child(instance_node, XML_NS_CIM_BINDING, WSMB_INCLUDE_RESULT_PROPERTY,
					filter->resultProp[i]);
				i++;
			}
		}

	} else if(filter->selectorset.count) {
		unsigned int i = 0;
		filter_node = ws_xml_add_child(node, ns, WSM_FILTER, NULL);
		if (!filter_node)
			return -1;
		node = ws_xml_add_child(filter_node, XML_NS_WS_MAN, WSM_SELECTOR_SET, NULL);
		if (!node)
			return -1;

		while (i < filter->selectorset.count) {
			if(filter->selectorset.selectors[i].type == 0) {
				instance_node = ws_xml_add_child(node, XML_NS_WS_MAN, WSM_SELECTOR,
					filter->selectorset.selectors[i].v.text);
				ws_xml_add_node_attr(instance_node, NULL, WSM_NAME, filter->selectorset.selectors[i].key);
			}
			else {
				epr_serialize(node, NULL, NULL, (epr_t *)filter->selectorset.selectors[i].v.epr, 1);
			}
			i++;
		}
	}
	else {
		return -1;
	}
	if(filter->dialect)
		ws_xml_add_node_attr(filter_node, NULL, WSM_DIALECT, filter->dialect);
	return r;

}

filter_t * filter_deserialize(WsXmlNodeH node, const char *ns)
{
	char *dialect = NULL;
	int properNum = 0;
	WsXmlAttrH attr = NULL;
	filter_t *filter = NULL;
	WsXmlNodeH instance_node = NULL;
	WsXmlNodeH entry_node = NULL;
        /* look for wse:Filter */
	WsXmlNodeH filter_node = ws_xml_get_child(node, 0, ns, WSM_FILTER);
	if(filter_node == NULL) return NULL;
	filter = u_zalloc(sizeof(filter_t));
	if (filter == NULL) {
		return NULL;
	}
	dialect = ws_xml_find_attr_value(filter_node, NULL, WSM_DIALECT);
	if(dialect)
		filter->dialect = u_strdup(dialect);
	else{
		attr = ws_xml_get_node_attr(filter_node, 0);
		if(attr) {
			filter->dialect = u_strdup(ws_xml_get_attr_value(attr));
		}
		else
			filter->dialect = u_strdup(WSM_XPATH_FILTER_DIALECT);
	}
	if(strcmp(filter->dialect , WSM_ASSOCIATION_FILTER_DIALECT) == 0) {
		int i = 0;
		instance_node = ws_xml_get_child(filter_node, 0, XML_NS_CIM_BINDING, WSMB_ASSOCIATED_INSTANCES);
		if(instance_node) {
			filter->assocType = 0;
		}
		else {
			instance_node = ws_xml_get_child(filter_node, 0, XML_NS_CIM_BINDING, WSMB_ASSOCIATION_INSTANCES);
			if(instance_node) {
				filter->assocType = 1;
			}
			else
				goto CLEANUP;
		}
		filter->epr = epr_deserialize(instance_node, XML_NS_CIM_BINDING, WSMB_OBJECT, 1);
		entry_node = ws_xml_get_child(instance_node, 0, XML_NS_CIM_BINDING, WSMB_ASSOCIATION_CLASS_NAME);
		if(entry_node)
			filter->assocClass = u_strdup(ws_xml_get_node_text_safe(entry_node));
		entry_node = ws_xml_get_child(instance_node, 0, XML_NS_CIM_BINDING, WSMB_ROLE);
		if(entry_node)
			filter->role = u_strdup(ws_xml_get_node_text_safe(entry_node));
		entry_node = ws_xml_get_child(instance_node, 0, XML_NS_CIM_BINDING, WSMB_RESULT_CLASS_NAME);
		if(entry_node)
			filter->resultClass = u_strdup(ws_xml_get_node_text_safe(entry_node));
		entry_node = ws_xml_get_child(instance_node, 0, XML_NS_CIM_BINDING, WSMB_RESULT_ROLE);
		if(entry_node)
			filter->resultRole = u_strdup(ws_xml_get_node_text_safe(entry_node));
		properNum = ws_xml_get_child_count(instance_node) - 4;
		filter->resultProp = u_zalloc(properNum * sizeof(char*));
		while(i < properNum) {
			filter_node = ws_xml_get_child(instance_node, i, XML_NS_CIM_BINDING, WSMB_INCLUDE_RESULT_PROPERTY);
			if(filter_node == NULL)
				break;
			filter->resultProp[i] = u_strdup(ws_xml_get_node_text_safe(filter_node));
			i++;
		}
		filter->PropNum = i;
	}
	else if(strcmp(filter->dialect, WSM_SELECTOR_FILTER_DIALECT) == 0) {
		unsigned int i = 0;
		filter_node = ws_xml_get_child(filter_node, 0, XML_NS_WS_MAN, WSM_SELECTOR_SET);
		if(filter_node == NULL)
			goto CLEANUP;
		filter->selectorset.count = ws_xml_get_child_count(filter_node);
		filter->selectorset.selectors = u_malloc(sizeof(key_value_t) * filter->selectorset.count );
		while(i < filter->selectorset.count) {
                  const char *key;
                  const char *text;
                  epr_t *epr;
			entry_node = ws_xml_get_child(filter_node, i, XML_NS_WS_MAN, WSM_SELECTOR);
			if(entry_node == NULL) break;
			attr = ws_xml_find_node_attr(entry_node, NULL, WSM_NAME);
			if(attr) {
				key = ws_xml_get_attr_value(attr);
			}
                  else {                          
                    key = NULL;
                  }
			instance_node = ws_xml_get_child(entry_node, 0, XML_NS_ADDRESSING, WSA_EPR);
			if(instance_node) {
				epr = epr_deserialize(instance_node, NULL, NULL, 1);
                          text = NULL;
			}
			else {
				text = ws_xml_get_node_text_safe(entry_node);
                          epr = NULL;
			}
                  key_value_create(key, text, epr, filter->selectorset.selectors + i);
                  if (epr) { /* key_value_create() did a epr_copy */
                    epr_destroy(epr);
                  }
			i++;
		}
	}
	else
		filter->query = u_strdup(ws_xml_get_node_text_safe(filter_node));

	return filter;

CLEANUP:
	filter_destroy(filter);
	return NULL;
}
