/*******************************************************************************
 * Copyright (c) 2005, 2011 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.metatype.impl;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import org.eclipse.equinox.metatype.EquinoxAttributeDefinition;
import org.eclipse.equinox.metatype.EquinoxObjectClassDefinition;
import org.eclipse.equinox.metatype.impl.Persistence.Writer;
import org.osgi.framework.Bundle;

/**
 * Implementation of ObjectClassDefinition
 */
public class ObjectClassDefinitionImpl extends LocalizationElement implements EquinoxObjectClassDefinition, Cloneable {
	private static final Comparator<Icon> iconComparator = new Comparator<Icon>() {
		@Override
		public int compare(Icon icon1, Icon icon2) {
			return icon1.getIconSize().compareTo(icon2.getIconSize());
		}
	};

	private final String _name;
	private final String _id;
	private final String _description;
	private final int _type;
	private final List<AttributeDefinitionImpl> _required = new ArrayList<>(7);
	private final List<AttributeDefinitionImpl> _optional = new ArrayList<>(7);
	private final ExtendableHelper helper;

	private volatile List<Icon> icons = null;

	/*
	 * Constructor of class ObjectClassDefinitionImpl.
	 */
	public ObjectClassDefinitionImpl(String name, String description, String id, String localization, Map<String, Map<String, String>> extensionAttributes) {
		this(name, description, id, 0, localization, new ExtendableHelper(extensionAttributes));
	}

	/*
	 * Constructor of class ObjectClassDefinitionImpl.
	 */
	public ObjectClassDefinitionImpl(String name, String description, String id, int type, String localization, ExtendableHelper helper) {
		super(localization);
		this._name = name;
		this._id = id;
		this._description = description;
		this._type = type;
		this.helper = helper;
	}

	/*
	 * 
	 */
	@Override
	public Object clone() {

		ObjectClassDefinitionImpl ocd = new ObjectClassDefinitionImpl(_name, _description, _id, _type, getLocalization(), helper);
		for (AttributeDefinitionImpl ad : _required) {
			ocd.addAttributeDefinition((AttributeDefinitionImpl) ad.clone(), true);
		}
		for (AttributeDefinitionImpl ad : _optional) {
			ocd.addAttributeDefinition((AttributeDefinitionImpl) ad.clone(), false);
		}
		if (icons != null) {
			ocd.setIcons(new ArrayList<Icon>(icons));
		}
		return ocd;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.service.metatype.ObjectClassDefinition#getName()
	 */
	public String getName() {
		return getLocalized(_name);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.service.metatype.ObjectClassDefinition#getID()
	 */
	public String getID() {
		return _id;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.service.metatype.ObjectClassDefinition#getDescription()
	 */
	public String getDescription() {
		return getLocalized(_description);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.service.metatype.ObjectClassDefinition#getAttributeDefinitions(int)
	 */
	@Override
	public EquinoxAttributeDefinition[] getAttributeDefinitions(int filter) {

		EquinoxAttributeDefinition[] atts;
		switch (filter) {
			case REQUIRED :
				atts = new EquinoxAttributeDefinition[_required.size()];
				_required.toArray(atts);
				return atts;
			case OPTIONAL :
				atts = new EquinoxAttributeDefinition[_optional.size()];
				_optional.toArray(atts);
				return atts;
			case ALL :
			default :
				atts = new EquinoxAttributeDefinition[_required.size() + _optional.size()];
				int i = 0;
				for (AttributeDefinitionImpl attr : _required) {
					atts[i] = attr;
					i++;
				}
				for (AttributeDefinitionImpl attr : _optional) {
					atts[i] = attr;
					i++;
				}
				return atts;
		}
	}

	/*
	 * Method to add one new AD to ObjectClassDefinition.
	 */
	void addAttributeDefinition(AttributeDefinitionImpl ad, boolean isRequired) {

		if (isRequired) {
			_required.add(ad);
		} else {
			_optional.add(ad);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.service.metatype.ObjectClassDefinition#getIcon(int)
	 */
	public InputStream getIcon(int sizeHint) throws IOException {
		// The parameter simply represents a requested size. This method should never return null if an
		// icon exists.
		// Temporary icon to hold the requested size for use in binary search comparator.
		Icon icon = new Icon(null, sizeHint, null);
		@SuppressWarnings("hiding")
		// Use a local reference to the icon list to be sure we don't suddenly start using a new one.
		List<Icon> icons = this.icons;
		// Icons will be null if none were specified.
		if (icons == null)
			return null;
		int index = Collections.binarySearch(icons, icon, iconComparator);
		if (index < 0) {
			// If the index is less than zero, there wasn't an exact match.
			// Compute the insertion point. This will be the index of the first icon whose 
			// size was greater than the requested size, or the list's length if there were none.
			int insertionPoint = -(index + 1);
			Icon lessThan = insertionPoint == 0 ? null : icons.get(insertionPoint - 1);
			Icon greaterThan = insertionPoint == icons.size() ? null : icons.get(insertionPoint);
			if (lessThan == null)
				// There were no icons whose size was smaller than the requested size.
				icon = greaterThan;
			else if (greaterThan == null)
				// There were no icons whose size was greater than the requested size.
				icon = lessThan;
			else {
				// There was at least one icon with a smaller size and at least one with
				// a greater size than the requested size. Compute the average to see which one to choose.
				int average = (greaterThan.getIconSize() + lessThan.getIconSize()) / 2;
				if (sizeHint < average)
					// The smaller icon is closer to the requested size.
					icon = lessThan;
				else
					// The larger icon is closer to the requested size.
					icon = greaterThan;
			}
		} else
			// The index was greater than or equal to zero, indicating the index of an exact match.
			icon = icons.get(index);
		Bundle b = icon.getIconBundle();
		URL[] urls = FragmentUtils.findEntries(b, getLocalized(icon.getIconName()));
		if (urls != null && urls.length > 0) {
			return urls[0].openStream();
		}
		return null;
	}

	void setIcons(List<Icon> icons) {
		// Do nothing if icons is null or empty.
		if (icons == null || icons.isEmpty())
			return;
		// Prepare the list of icons for binary searches as in getIcon(int).
		Collections.sort(icons, iconComparator);
		// Make the list unmodifiable for safe binary searches without copying.
		// We assume the caller makes no modifications to the list.
		this.icons = Collections.unmodifiableList(icons);
	}

	/**
	 * Method to set the resource bundle for this OCD and all its ADs.
	 */
	void setResourceBundle(String assignedLocale, Bundle bundle) {
		setLocaleAndBundle(assignedLocale, bundle);
		for (AttributeDefinitionImpl ad : _required) {
			ad.setLocaleAndBundle(assignedLocale, bundle);
		}
		for (AttributeDefinitionImpl ad : _optional) {
			ad.setLocaleAndBundle(assignedLocale, bundle);
		}
	}

	@Override
	public Map<String, String> getExtensionAttributes(String schema) {
		return helper.getExtensionAttributes(schema);
	}

	@Override
	public Set<String> getExtensionUris() {
		return helper.getExtensionUris();
	}

	void getStrings(Set<String> strings) {
		helper.getStrings(strings);
		strings.add(_description);
		strings.add(_id);
		strings.add(_name);
		strings.add(getLocalization());
		@SuppressWarnings("hiding")
		List<Icon> icons = this.icons;
		if (icons != null) {
			for (Icon icon : icons) {
				icon.getStrings(strings);
			}
		}
	}

	static ObjectClassDefinitionImpl load(Bundle b, LogTracker logger, Persistence.Reader reader) throws IOException {
		String description = reader.readString();
		String id = reader.readString();
		String name = reader.readString();
		int type = reader.readInt();
		String localization = reader.readString();
		ExtendableHelper helper = ExtendableHelper.load(reader);
		ObjectClassDefinitionImpl result = new ObjectClassDefinitionImpl(name, description, id, type, localization, helper);

		int numIcons = reader.readInt();
		List<Icon> icons = null;
		if (numIcons > 0) {
			icons = new ArrayList<>(numIcons);
			for (int i = 0; i < numIcons; i++) {
				icons.add(Icon.load(reader, b));
			}
		}
		result.setIcons(icons);

		int numRequired = reader.readInt();
		for (int i = 0; i < numRequired; i++) {
			result.addAttributeDefinition(AttributeDefinitionImpl.load(reader, logger), true);
		}
		int numOptional = reader.readInt();
		for (int i = 0; i < numOptional; i++) {
			result.addAttributeDefinition(AttributeDefinitionImpl.load(reader, logger), false);
		}

		return result;
	}

	void write(Writer writer) throws IOException {
		writer.writeString(_description);
		writer.writeString(_id);
		writer.writeString(_name);
		writer.writeInt(_type);
		writer.writeString(getLocalization());
		helper.write(writer);
		List<Icon> curIcons = this.icons;
		writer.writeInt(curIcons == null ? 0 : curIcons.size());
		if (curIcons != null) {
			for (Icon icon : curIcons) {
				icon.write(writer);
			}
		}
		writer.writeInt(_required.size());
		for (AttributeDefinitionImpl ad : _required) {
			ad.write(writer);
		}
		writer.writeInt(_optional.size());
		for (AttributeDefinitionImpl ad : _optional) {
			ad.write(writer);
		}
	}
}
