package me.chyxion.tigon.webmvc;

import java.io.File;
import lombok.Getter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.http.MediaType;
import org.springframework.core.io.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;

/**
 * @version 0.0.1
 * @since 0.0.1
 * @author Shaun Chyxion <br>
 * chyxion@163.com <br>
 * Jan 16, 2015 5:33:30 PM
 */
@Slf4j
@Getter
public class ResourceModel {

    private String contentType;
    private long contentLength;
    private String name;
    private Resource resource;

    public ResourceModel(final Resource resource,
        String contentType, long contentLength, String name) throws IOException {
        Assert.notNull(resource, "Resource model resource could not be null");
        Assert.state(!(InputStreamResource.class == 
            resource.getClass() && contentLength <= 0), 
            "Input stream resource content length must provide.");
        this.resource = resource;
        this.contentType = contentType;
        this.contentLength = contentLength > 0 ? 
            contentLength : resource.contentLength();
        this.name = name;
    }

    public ResourceModel(final File file, final String contentType, final String name) {
        this.resource = new FileSystemResource(file);
        this.contentType = contentType;
        this.contentLength = file.length();
        this.name = StringUtils.defaultIfBlank(name, file.getName());
    }
    
    public ResourceModel(final InputStream inputStream,
        String contentType, long contentLength, String name) {
        Assert.notNull(inputStream, "Resource model input stream could not be null");
        Assert.state(contentLength > 0, 
            "Input stream resource content length must provide.");
        this.contentType = contentType;
        this.contentLength = contentLength;
        this.resource = new InputStreamResource(inputStream);
        this.name = name;
    }

    public ResourceModel(byte[] data, String contentType, String name) {
        Assert.notNull(data, "Resource model data could not be null");
        this.resource = new ByteArrayResource(data);
        this.contentType = contentType;
        this.contentLength = data.length;
        this.name = name;
    }

    /**
     * @return the contentType
     */
    public String getContentType() {
        if (StringUtils.isBlank(contentType)) {
            log.debug("Resource Content Type Is Blank, Try To Guess From Name [{}].", name);
            // from file name
            if (StringUtils.isNotBlank(name)) {
                contentType = URLConnection.guessContentTypeFromName(name);
                log.debug("Guess Content Type [{}] From File Name [{}].", contentType, name);
            }
            // use default
            if (StringUtils.isBlank(contentType)) {
                contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
                log.debug("Use Default Content Type [{}].", contentType);
            }
        }
        return contentType;
    }
}
