package com.wizzardo.http.html;

import com.wizzardo.tools.collections.CollectionTools;

import java.util.*;

/**
 * Created by wizzardo on 08.01.15.
 */
public class Tag {
    protected Map<String, String> attrs;
    protected String name;
    protected Body body;

    Tag() {
    }

    public Tag(String name) {
        this.name = name;
    }

    public void render(Renderer renderer) {
        renderer.append('<').append(name);
        if (attrs != null) {
            for (Map.Entry<String, String> entry : attrs.entrySet()) {
                renderer.append(' ').append(entry.getKey()).append("=\"").append(entry.getValue()).append('"');
            }
        }

        if (body == null) {
            renderer.append("/>");
        } else {
            renderer.append(">");
            body.render(renderer);
            renderer.append("</").append(name).append('>');
        }
    }

    public <T> Tag each(Collection<T> collection, CollectionTools.Closure<Tag, T> closure) {
        if (collection != null)
            for (T t : collection) {
                add(closure.execute(t));
            }
        return this;
    }

    public <T> Tag each(T[] collection, CollectionTools.Closure<Tag, T> closure) {
        if (collection != null)
            for (T t : collection) {
                add(closure.execute(t));
            }
        return this;
    }

    public Tag add(Tag tag) {
        if (body == null)
            body = new Body();
        body.add(tag);
        return this;
    }

    public Tag attr(String name, String value) {
        if (attrs == null)
            attrs = new LinkedHashMap<>();
        attrs.put(name, value);
        return this;
    }

    public Tag id(String id) {
        return attr("id", id);
    }

    public Tag clazz(String clazz) {
        return attr("class", clazz);
    }

    public Tag style(String style) {
        return attr("style", style);
    }

    public Tag text(String text) {
        return add(new Tag.Text(text));
    }

    public static class Body {
        private List<Tag> tags = new ArrayList<>();

        public void add(Tag tag) {
            tags.add(tag);
        }

        public void render(Renderer renderer) {
            for (Tag tag : tags)
                tag.render(renderer);
        }
    }

    static class Doctype extends Tag {

        @Override
        public void render(Renderer renderer) {
            renderer.append("<!DOCTYPE html>");
        }
    }

    public static class Text extends Tag {
        public Text(String text) {
            super(text);
        }

        @Override
        public void render(Renderer renderer) {
            renderer.append(name);
        }

        @Override
        public Tag attr(String name, String value) {
            throw new IllegalStateException("Text tag can not have any attributes");
        }

        @Override
        public Tag add(Tag tag) {
            throw new IllegalStateException("Text tag can not have any inner tags");
        }
    }

    public static class A extends Tag {
        public A() {
            super("a");
        }

        public A href(String url) {
            attr("href", url);
            return this;
        }
    }

    public static class Script extends Tag {
        public Script() {
            this("text/javascript");
        }

        public Script(String type) {
            super("script");
            body = new Body();
            attr("type", type);
        }

        public Script src(String url) {
            attr("src", url);
            return this;
        }
    }

    public static class Link extends Tag {
        public Link() {
            this("stylesheet");
        }

        public Link(String rel) {
            super("link");
            attr("rel", rel);
        }

        public Link href(String url) {
            attr("href", url);
            return this;
        }
    }
}

@@ -3911,11 +3911,629 @@
  %7D%0A    %7D
+%0A%0A    public static class Select extends Tag %7B%0A        public Select(List list) %7B%0A            super(%22select%22);%0A            for (Object o : list) %7B%0A                String s = String.valueOf(o);%0A                add(new Tag(%22option%22).attr(%22value%22, s).text(s));%0A            %7D%0A        %7D%0A%0A        public Select(Map%3C?, ?%3E map) %7B%0A            super(%22select%22);%0A            for (Map.Entry e : map.entrySet()) %7B%0A                String key = String.valueOf(e.getKey());%0A                String value = String.valueOf(e.getValue());%0A                add(new Tag(%22option%22).attr(%22value%22, key).text(value));%0A            %7D%0A        %7D%0A    %7D
 %0A%7D%0A

add Select Tag