/*******************************************************************************
 * Copyright (c) 2000, 2006 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.ui.examples.propertysheet;

import java.util.ArrayList;

import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;

/**
 * PropertySource containing street information pertenant to Address
 */
public class StreetAddress implements IPropertySource {

    //properties
    private Integer buildNo;

    private String aptBox;

    private String streetName;

    //default property values
    private static final Integer BUILD_NO_DEFAULT = Integer.valueOf(0);

    private static final String APTBOX_DEFAULT = MessageUtil
            .getString("unspecified"); //$NON-NLS-1$

    private static final String STREETNAME_DEFAULT = MessageUtil
            .getString("unspecified"); //$NON-NLS-1$

    //property unique keys
    public static final String P_ID_BUILD_NO = "Street.buildingNo"; //$NON-NLS-1$

    public static final String P_ID_APTBOX = "Street.aptNo"; //$NON-NLS-1$

    public static final String P_ID_STREET = "Street.street"; //$NON-NLS-1$

    //property display keys
    public static final String P_BUILD_NO = MessageUtil
            .getString("building_number"); //$NON-NLS-1$

    public static final String P_APTBOX = MessageUtil
            .getString("apt.no_or_box.no"); //$NON-NLS-1$

    public static final String P_STREET = MessageUtil.getString("street"); //$NON-NLS-1$

    private static ArrayList<TextPropertyDescriptor> descriptors;

    static {
        descriptors = new ArrayList<>();
        descriptors.add(new TextPropertyDescriptor(P_ID_BUILD_NO,
                P_BUILD_NO));
        descriptors
                .add(new TextPropertyDescriptor(P_ID_APTBOX, P_APTBOX));
        descriptors
                .add(new TextPropertyDescriptor(P_ID_STREET, P_STREET));
    }

    /**
     * Street Default Constructor.
     */
    public StreetAddress() {
        super();
    }

    /**
     * Convenience Street constructor. AptBox set to default
     */
    public StreetAddress(int buildNo, String streetName) {
        super();
        setBuildNo(Integer.valueOf(buildNo));
        setStreetName(streetName);
    }

    /**
     * Convenience Street constructor.
     */
    public StreetAddress(int buildNo, String aptBox, String streetName) {
        super();
        setBuildNo(Integer.valueOf(buildNo));
        setAptBox(aptBox);
        setStreetName(streetName);
    }

    @Override
	public boolean equals(Object ob) {
        return toString().equals(ob.toString());
    }

    /**
     * the appartment number
     */
    private String getAptBox() {
        if (aptBox == null)
            aptBox = APTBOX_DEFAULT;
        return aptBox;
    }

    /**
     * Returns the building number
     */
    private Integer getBuildNo() {
        if (buildNo == null)
            buildNo = BUILD_NO_DEFAULT;
        return buildNo;
    }

    /**
     * Returns the descriptors
     */
    private static ArrayList<TextPropertyDescriptor> getDescriptors() {
        return descriptors;
    }

    @Override
	public Object getEditableValue() {
        return this.toString();
    }

    @Override
	public IPropertyDescriptor[] getPropertyDescriptors() {
        return getDescriptors().toArray(
                new IPropertyDescriptor[getDescriptors().size()]);
    }

    /**
     * The <code>Name</code> implementation of this
     * <code>IPropertySource</code> method returns the following properties
     *
     * 	1) P_BUILD_NO returns java.lang.Integer
     * 	2) P_APTBOX returns java.lang.String
     *	3) P_STREET returns java.lang.String
     */
    @Override
	public Object getPropertyValue(Object propKey) {
        if (propKey.equals(P_ID_BUILD_NO))
            return getBuildNo().toString();
        if (propKey.equals(P_ID_APTBOX))
            return getAptBox();
        if (propKey.equals(P_ID_STREET))
            return getStreetName();
        return null;
    }

    /**
     * Returns the street name
     */
    private String getStreetName() {
        if (streetName == null)
            streetName = STREETNAME_DEFAULT;
        return streetName;
    }

    @Override
	public int hashCode() {
        return toString().hashCode();
    }

    @Override
	public boolean isPropertySet(Object property) {
        if (property.equals(P_ID_BUILD_NO))
            return getBuildNo() != BUILD_NO_DEFAULT;
        if (property.equals(P_ID_APTBOX))
            return getAptBox() != APTBOX_DEFAULT;
        if (property.equals(P_ID_STREET))
            return getStreetName() != STREETNAME_DEFAULT;
        return false;
    }

    @Override
	public void resetPropertyValue(Object property) {
        if (property.equals(P_ID_BUILD_NO)) {
            setBuildNo(BUILD_NO_DEFAULT);
            return;
        }
        if (property.equals(P_ID_APTBOX)) {
            setAptBox(APTBOX_DEFAULT);
            return;
        }
        if (property.equals(P_ID_STREET)) {
            setStreetName(STREETNAME_DEFAULT);
            return;
        }
    }

    /**
     * Sets the appartment number
     */
    private void setAptBox(String newAptBox) {
        aptBox = newAptBox;
    }

    /**
     * Sets the building number
     */
    private void setBuildNo(Integer newBuildNo) {
        buildNo = newBuildNo;
    }

    /**
     * The <code>Name</code> implementation of this
     * <code>IPropertySource</code> method
     * defines the following Setable properties
     *
     * 	1) P_BUILD_NO expects java.lang.Integer
     * 	2) P_APTBOX expects java.lang.String
     *	3) P_STREET expects java.lang.String
     */
    @Override
	public void setPropertyValue(Object name, Object value) {
        if (name.equals(P_ID_BUILD_NO)) {
            try {
                setBuildNo(Integer.valueOf(Integer.parseInt((String) value)));
            } catch (NumberFormatException e) {
                setBuildNo(BUILD_NO_DEFAULT);
            }
            return;
        }
        if (name.equals(P_ID_APTBOX)) {
            setAptBox((String) value);
            return;
        }
        if (name.equals(P_ID_STREET)) {
            setStreetName((String) value);
            return;
        }
    }

    /**
     * Sets the street name
     */
    private void setStreetName(String newStreetName) {
        streetName = newStreetName;
    }

    /**
     * The value as displayed in the Property Sheet. Will not print default values
     * @return java.lang.String
     */
    @Override
	public String toString() {
        StringBuilder outStringBuilder = new StringBuilder();
        if (!getAptBox().equals(APTBOX_DEFAULT)) {
            outStringBuilder.append(getAptBox());
            outStringBuilder.append(", "); //$NON-NLS-1$
        }
        if (!getBuildNo().equals(BUILD_NO_DEFAULT)) {
            outStringBuilder.append(getBuildNo());
            outStringBuilder.append(" "); //$NON-NLS-1$
        }
        if (!getStreetName().equals(STREETNAME_DEFAULT)) {
            outStringBuilder.append(getStreetName());
        }
        return outStringBuilder.toString();
    }
}
