package com.jscape.inet.http.protocol.marshaling;

import com.jscape.inet.http.protocol.messages.ContentRange;
import com.jscape.inet.http.protocol.messages.Headers;

import java.util.Scanner;

/**
 * @author Alex Usun
 */
@SuppressWarnings("unchecked")
public enum ContentHeader {
    
    CONTENT_LENGTH() {
        @Override
        public <T> T of(Headers headers) {
            return (T) headers.longValueOf("Content-Length", 10);
        }
    
        @Override
        public void set(Headers headers, Object value) {
            headers.set("Content-Length", value.toString());
        }
    },
    CONTENT_RANGE() {
        @Override
        public <T> T of(Headers headers) {
            String data = headers.valueOf("Content-Range");
            if (data == null) {
                return null;
            }
            
            try {
                Scanner scanner = new Scanner(data);
                scanner.useDelimiter(" ");
                String unit = scanner.next();
                scanner.useDelimiter("/");
                String rangeData = scanner.next();
                Long start = null;
                Long end = null;
                if (!"*".equals(rangeData)) {
                    Scanner rangeScanner = new Scanner(rangeData.trim());
                    rangeScanner.useDelimiter("-");
                    start = Long.valueOf(rangeScanner.next(), 10);
                    end = Long.valueOf(rangeScanner.next(), 10);
                }
                
                String sizeData = scanner.next();
                Long size = !"*".equals(sizeData) ? Long.valueOf(sizeData.trim(), 10) : null;
                
                return (T) new ContentRange(unit, start, end, size);
            } catch (Exception e) {
                return null;
            }
        }
    
        @Override
        public void set(Headers headers, Object value) {
            ContentRange range = (ContentRange) value;
            
            if (range.start != null && range.size != null) {
                String data = String.format("%s %s-%s/%s", range.unit, range.start, range.end, range.size);
                headers.set("Content-Range", data);
            } else if (range.start != null) {
                String data = String.format("%s %s-%s/*", range.unit, range.start, range.end);
                headers.set("Content-Range", data);
            } else if (range.size != null) {
                String data = String.format("%s */%s", range.unit, range.size);
                headers.set("Content-Range", data);
            }
        }
    },
    TRANSFER_ENCODING_CHUNKED() {
        @Override
        public <T> T of(Headers headers) {
            String data = headers.valueOf("Transfer-Encoding");
            return (T) ((Boolean) "chunked".equalsIgnoreCase(data));
        }
    
        @Override
        public void set(Headers headers, Object value) {
            headers.set("Transfer-Encoding", "chunked");
        }
    },
    CONTENT_ENCODING() {
        @Override
        public <T> T of(Headers headers) {
            return (T) headers.valueOf("Content-Encoding");
        }
    
        @Override
        public void set(Headers headers, Object value) {
            headers.set("Content-Encoding", value.toString());
        }
    },
    CONTENT_TYPE() {
        @Override
        public <T> T of(Headers headers) {
            return (T) headers.valueOf("Content-Type");
        }
    
        @Override
        public void set(Headers headers, Object value) {
            headers.set("Content-Type", value.toString());
        }
    };
    
    public abstract <T> T of(Headers headers);
    
    public abstract void set(Headers headers, Object value);
}
