package uk.ac.starlink.ttools.cone;

import uk.ac.starlink.task.Environment;
import uk.ac.starlink.task.Parameter;
import uk.ac.starlink.task.ParameterValueException;
import uk.ac.starlink.task.TaskException;

/**
 * Parameter for specifying SkyTiling values.
 *
 * @author   Mark Taylor
 * @since    13 Dec 2007
 */
public class TilingParameter extends Parameter<SkyTiling> {

    private static final String HTM_PREFIX = "htm";
    private static final String HEALPIX_RING_PREFIX = "healpixring";
    private static final String HEALPIX_NEST_PREFIX = "healpixnest";

    /**
     * Constructor.
     *
     * @param  name   parameter name
     */
    public TilingParameter( String name ) {
        super( name, SkyTiling.class, true );
        setPrompt( "Sky tiling scheme" );
        setUsage( HTM_PREFIX + "<level>" + "|"
                + HEALPIX_NEST_PREFIX + "<nside>" + "|"
                + HEALPIX_RING_PREFIX + "<nside>" );
        setNullPermitted( true );
        setDescription( new String[] {
            "<p>Describes the sky tiling scheme that is in use.",
            "One of the following values may be used:",
            "<ul>",
            "<li><code>" + HTM_PREFIX + "&lt;level&gt;</code>:",
                "Hierarchical Triangular Mesh with a level value of",
                "<code>level</code>.</li>",
            "<li><code>" + HEALPIX_NEST_PREFIX + "&lt;nside&gt;</code>:",
                "HEALPix using the Nest scheme with an nside value of",
                "<code>nside</code>.</li>",
            "<li><code>" + HEALPIX_RING_PREFIX + "&lt;nside&gt;</code>:",
                "HEALPix using the Ring scheme with an nside value of",
                "<code>nside</code>.</li>",
            "</ul>",
            "</p>",
        } );
    }

    public SkyTiling stringToObject( Environment env, String svalue )
            throws TaskException {
        String lvalue = svalue.toLowerCase();
        if ( lvalue.startsWith( HTM_PREFIX ) ) {
            int level = getNumberSuffix( svalue, HTM_PREFIX );
            return new HtmTiling( level );
        }
        else if ( lvalue.startsWith( HEALPIX_NEST_PREFIX ) ) {
            int nside = getNumberSuffix( svalue, HEALPIX_NEST_PREFIX );
            return new HealpixTiling( nside, true );
        }
        else if ( lvalue.startsWith( HEALPIX_RING_PREFIX ) ) {
            int nside = getNumberSuffix( svalue, HEALPIX_RING_PREFIX );
            return new HealpixTiling( nside, false );
        }
        else {
            throw new ParameterValueException( this, "Unknown tiling scheme \""
                                                   + svalue + "\"" );
        }
    }

    /**
     * Returns the value of this parameter as a SkyTiling object.
     *
     * @param  env  execution environment
     * @return   tiling value
     */
    public SkyTiling tilingValue( Environment env ) throws TaskException {
        return objectValue( env );
    }

    /**
     * Parses a string of the form &lt;prefix&gt;&lt;num&gt;, returning
     * the integer value of the &lt;num&gt; part.
     *
     * @param   value   string to parse
     * @param   prefix  prefix part
     * @return  integer value of suffix part
     * @throws  TaskException  if the parsing fails
     */
    private int getNumberSuffix( String value, String prefix ) 
            throws TaskException {
        String svalue = value.substring( prefix.length() );
        try {
            return Integer.parseInt( svalue );
        }
        catch ( NumberFormatException e ) {
            throw new ParameterValueException( this, "\"" + svalue + "\" "
                                             + "not numeric" );
        }
    }
}
