/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

/*
* This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
* Supported AMQP versions:
* 0-9
* 0-91
* 8-0
*/

package org.apache.qpid.server.protocol;

import java.util.SortedSet;
import java.util.Collections;
import java.util.TreeSet;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

public class ProtocolVersion  implements Comparable
{
    private final byte _majorVersion;
    private final byte _minorVersion;
    private final String _stringFormat;

    private ProtocolVersion(byte majorVersion, byte minorVersion)
    {
        _majorVersion = majorVersion;
        _minorVersion = minorVersion;
        _stringFormat = _majorVersion+"-"+_minorVersion;
    }

    public byte getMajorVersion()
    {
        return _majorVersion;
    }

    public byte getMinorVersion()
    {
        return _minorVersion;
    }

    public byte getActualMinorVersion()
    {
        return _minorVersion > 90 ? (byte) (_minorVersion / 10) : _minorVersion;
    }

    public byte getRevisionVersion()
    {
        return _minorVersion > 90 ? (byte) (_minorVersion % 10) : (byte) 0;
    }

    @Override
    public String toString()
    {
        return _stringFormat;
    }

    @Override
    public int compareTo(Object o)
    {
        ProtocolVersion pv = (ProtocolVersion) o;

        /* 
         * 0-8 has it's major and minor numbers the wrong way round (it's actually 8-0)...
         * so we need to deal with that case specially
         */

        if((_majorVersion == (byte) 8) && (_minorVersion == (byte) 0))
        {
            ProtocolVersion fixedThis = new ProtocolVersion(_minorVersion, _majorVersion);
            return fixedThis.compareTo(pv);
        }

        if((pv.getMajorVersion() == (byte) 8) && (pv.getMinorVersion() == (byte) 0))
        {
            ProtocolVersion fixedOther = new ProtocolVersion(pv.getMinorVersion(), pv.getMajorVersion());
            return this.compareTo(fixedOther);
        }

        if(_majorVersion > pv.getMajorVersion())
        {
            return 1;
        }
        else if(_majorVersion < pv.getMajorVersion())
        {
            return -1;
        }
        else if(_minorVersion > pv.getMinorVersion())
        {
            return 1;
        }
        else if(getMinorVersion() < pv.getMinorVersion())
        {
            return -1;
        }
        else
        {
            return 0;
        }

    }

    @Override
    public boolean equals(Object o)
    {
        return o != null && (o == this || (compareTo(o) == 0));
    }

    @Override
    public int hashCode()
    {
        return (0xFF & (int)_minorVersion) | ((0xFF & (int)_majorVersion) << 8);
    }

    public boolean isSupported()
    {
        return _supportedVersions.contains(this);
    }

    public static ProtocolVersion getLatestSupportedVersion()
    {
        return _supportedVersions.last();
    }

    private static final SortedSet<ProtocolVersion> _supportedVersions;
    private static final Map<String, ProtocolVersion> _nameToVersionMap =
                             new HashMap<String, ProtocolVersion>();
    private static final ProtocolVersion _defaultVersion;

    public static final ProtocolVersion v0_10 = new ProtocolVersion((byte)0,(byte)10);

    public static final ProtocolVersion v0_9 = new ProtocolVersion((byte)0,(byte)9);
    public static final ProtocolVersion v0_91 = new ProtocolVersion((byte)0,(byte)91);
    public static final ProtocolVersion v0_8 = new ProtocolVersion((byte)8,(byte)0);

    private static final Map<ProtocolVersion, ProtocolVersion> INSTANCES = new ConcurrentHashMap<ProtocolVersion,ProtocolVersion>();

    static
    {
        SortedSet<ProtocolVersion> versions = new TreeSet<ProtocolVersion>();

        versions.add(v0_10);
        _nameToVersionMap.put("0-10", v0_10);
        versions.add(v0_9);
        _nameToVersionMap.put("0-9", v0_9);
        versions.add(v0_91);
        _nameToVersionMap.put("0-91", v0_91);
        versions.add(v0_8);
        _nameToVersionMap.put("8-0", v0_8);
        _supportedVersions = Collections.unmodifiableSortedSet(versions);

        ProtocolVersion systemDefinedVersion =
            _nameToVersionMap.get(System.getProperty("org.apache.qpid.amqp_version"));

        _defaultVersion = (systemDefinedVersion == null)
                              ? getLatestSupportedVersion()
                              : systemDefinedVersion;
        INSTANCES.put(v0_10,v0_10);
        INSTANCES.put(v0_9,v0_9);
        INSTANCES.put(v0_91,v0_91);
        INSTANCES.put(v0_8, v0_8);
    }

    public static SortedSet<ProtocolVersion> getSupportedProtocolVersions()
    {
        return _supportedVersions;
    }

    public static ProtocolVersion parse(String name)
    {
        return _nameToVersionMap.get(name);
    }

    public static ProtocolVersion defaultProtocolVersion()
    {
        return _defaultVersion;
    }

    public static ProtocolVersion get(byte majorVersion, byte minorVersion)
    {
        ProtocolVersion pv = new ProtocolVersion(majorVersion, minorVersion);
        ProtocolVersion instance = INSTANCES.get(pv);
        return instance == null ? pv : instance;
    }


}
