/* 
 * Copyright 2015 by AVM GmbH <info@avm.de>
 *
 * This software contains free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License ("License") as 
 * published by the Free Software Foundation  (version 3 of the License). 
 * This software is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the copy of the 
 * License you received along with this software for more details.
 */

package de.avm.android.tr064.soap.ontel;

import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import de.avm.android.tr064.exceptions.BaseException;
import de.avm.android.tr064.exceptions.DataMisformatException;
import de.avm.android.tr064.model.CallLog;
import de.avm.android.tr064.net.SoapSSLClientFactory;
import de.avm.android.tr064.net.WebUtil;
import de.avm.android.tr064.soap.ISoapCredentials;

/* Soap implementation for the calllist-Interface */
public class GetCallList extends OnTelSoapHelper<CallLog>
{
    public static final int MIN_DAYS = 0;
    public static final int MAX_DAYS = 999;
    public static final int MIN_MAX = 0;
    public static final int MAX_MAX = 999;

    public static final String ERROR_OUT_OF_RANGE = "At least one parameter is out of range";
    public static final String ERROR_MISSING = "Too few parameters";
    public static final String ERROR_TYPE = "At least one parameter has invalid type";

    public enum ParameterSpec
    {
        /**
         * Calls of the most recent n days (1: today, 0:all)
         * See {@link #MIN_DAYS} and {@link #MAX_DAYS}
         * Argument is Integer for maxDays
         */
        RECENT_DAYS,
        /**
         * Calls since call with this id
         * Arguments are Long callUniqueId and Long callLogTimestamp
         */
        SINCE_ID,
        /**
         * Most recent n calls (0: all)
         * See {@link #MIN_MAX} and {@link #MAX_MAX}
         * Argument is Integer for maxCount
         */
        RECENT_COUNT
    }

    private String mUrlParameters = null;

    /**
     * Requests call list
     * @param soapCredentials
     */
    public GetCallList(ISoapCredentials soapCredentials)
    {
        super(soapCredentials);
    }

    /**
     * Requests call list
     * @param soapCredentials
     * @param spec
     *      Meaning of parameter
     * @param parameters
     *      Parameter value(s), arguments see GetCallList.ParameterSpec
     *
     */
    public GetCallList(ISoapCredentials soapCredentials, ParameterSpec spec, Object... parameters)
    {
        super(soapCredentials);

        switch (spec)
        {
            case RECENT_DAYS:
            {
                if ((parameters == null) || (parameters.length < 1))
                    throw new IllegalArgumentException(ERROR_MISSING);
                if (parameters[0] instanceof Integer)
                {
                    int value = (Integer)parameters[0];
                    if ((value < MIN_DAYS) || (value > MAX_DAYS))
                        throw new IllegalArgumentException(ERROR_OUT_OF_RANGE);
                    if (value == 0) return;
                    mUrlParameters = "&days=" + Integer.toString(value);
                }
                else throw new IllegalArgumentException(ERROR_TYPE);
                break;
            }

            case RECENT_COUNT:
            {
                if ((parameters == null) || (parameters.length < 1))
                    throw new IllegalArgumentException(ERROR_MISSING);
                if (parameters[0] instanceof Integer)
                {
                    int value = (Integer)parameters[0];
                    if ((value < MIN_MAX) || (value > MAX_MAX))
                        throw new IllegalArgumentException(ERROR_OUT_OF_RANGE);
                    if (value == 0) return;
                    mUrlParameters = "&max=" + Integer.toString(value);
                }
                else throw new IllegalArgumentException(ERROR_TYPE);
                break;
            }

            case SINCE_ID:
            {
                if ((parameters == null) || (parameters.length < 2))
                    throw new IllegalArgumentException(ERROR_MISSING);
                if ((parameters[0] instanceof Long) && (parameters[1] instanceof Long))
                {
                    long id = (Long)parameters[0];
                    long timestamp = (Long)parameters[1];
                    mUrlParameters = "&id=" + Long.toString(id) +
                            "&timestamp=" + Long.toString(timestamp);
                }
                else throw new IllegalArgumentException(ERROR_TYPE);
                break;
            }
        }
    }

    /**
     * Requests call list
     * @param soapCredentials
     * @param maxSize
     *      the most recent entries in a list of maximum size (0 means all entries)
     * @deprecated Use
     */
    public GetCallList(ISoapCredentials soapCredentials, int maxSize)
    {
        this(soapCredentials, ParameterSpec.RECENT_COUNT, maxSize);
    }

    @Override
	public CallLog getQualifiedResult()
			throws DataMisformatException, BaseException, IOException
	{
		String url = getValueByName("NewCallListURL", getSoapBody());
		
		int port = mSoapCredentials.getPort(true);
		if (port < 1)
			// should not occur, because action used this port
			throw new DataMisformatException("No SSL port available.");

		if (mUrlParameters != null) url += mUrlParameters;
		return new CallLog(WebUtil.getContentAsInputStream(
				fixDownloadUrl(URLDecoder.decode(url, Charset.defaultCharset().name())),
				SoapSSLClientFactory.getClientWithDigestAuth(port,
						mSoapCredentials.getUsername(), mSoapCredentials.getPassword(),
						mSoapCredentials.getPinningStore())));
	}

	@Override
	public String getSoapMethod()
	{
		return "GetCallList";
	}
}
