package org.xbib.io.webdav.common;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xbib.io.webdav.api.DavConstants;
import org.xbib.io.webdav.api.XMLizable;

/**
 * <code>Status</code> encapsulating the 'status' present in multi status
 * responses.
 */
public class Status implements DavConstants, XMLizable {

    private final String version;
    private final int code;
    private final String phrase;

    public Status(int code) {
        version = "HTTP/1.1";
        this.code = code;
        phrase = DavException.getStatusPhrase(code);
    }

    public Status(String version, int code, String phrase) {
        this.version = version;
        this.code = code;
        this.phrase = phrase;
    }

    public int getStatusCode() {
        return code;
    }

    public Element toXml(Document document) {
        String statusLine = version + " " + code + " " + phrase;
        Element e = DomUtil.createElement(document, XML_STATUS, NAMESPACE);
        DomUtil.setText(e, statusLine);
        return e;
    }

    /**
     * Parse the given status line and return a new <code>Status</code> object.
     *
     * @param statusLine
     * @return a new <code>Status</code>
     */
    public static Status parse(String statusLine) {
        if (statusLine == null) {
            throw new IllegalArgumentException("Unable to parse status line from null xml element.");
        }
        Status status;

        // code copied from org.apache.commons.httpclient.StatusLine
        int length = statusLine.length();
        int at = 0;
        int start = 0;
        try {
            while (Character.isWhitespace(statusLine.charAt(at))) {
                ++at;
                ++start;
            }
            if (!"HTTP".equals(statusLine.substring(at, at += 4))) {
                //LOG.log(Level.WARNING, "Status-Line '" + statusLine + "' does not start with HTTP");
            }
            //handle the HTTP-Version
            at = statusLine.indexOf(' ', at);
            if (at <= 0) {
                // LOG.log(Level.WARNING, "Unable to parse HTTP-Version from the status line: '" + statusLine + "'");
            }
            String version = (statusLine.substring(start, at)).toUpperCase();
            //advance through spaces
            while (statusLine.charAt(at) == ' ') {
                at++;
            }
            //handle the Status-Code
            int code;
            int to = statusLine.indexOf(' ', at);
            if (to < 0) {
                to = length;
            }
            try {
                code = Integer.parseInt(statusLine.substring(at, to));
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("Unable to parse status code from status line: '" + statusLine + "'");
            }
            //handle the Reason-Phrase
            String phrase = "";
            at = to + 1;
            if (at < length) {
                phrase = statusLine.substring(at).trim();
            }

            status = new Status(version, code, phrase);

        } catch (StringIndexOutOfBoundsException e) {
            throw new IllegalArgumentException("Status-Line '" + statusLine + "' is not valid");
        }
        return status;
    }
}