/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jooby.internal;

import java.util.Arrays;
import java.util.Map;

import org.jooby.Err;
import org.jooby.MediaType;
import org.jooby.Renderer;
import org.jooby.View;

public class DefaulErrRenderer implements Renderer {

  private boolean showStacktrace;

  public DefaulErrRenderer(final boolean stacktrace) {
    this.showStacktrace = stacktrace;
  }

  @SuppressWarnings("unchecked")
  @Override
  public void render(final Object object, final Context ctx) throws Exception {
    if (object instanceof View) {
      View view = (View) object;
      // assume it is the default error handler
      if (Err.DefHandler.VIEW.equals(view.name())) {
        Map<String, Object> model = (Map<String, Object>) view.model().get("err");
        Object status = model.get("status");
        Object reason = model.get("reason");
        Object message = model.get("message");
        String[] stacktrace = this.showStacktrace ? (String[]) model.get("stacktrace") : null;

        StringBuilder html = new StringBuilder("<!doctype html>\n")
            .append("<html>\n")
            .append("<head>\n")
            .append("<meta charset=\"").append(ctx.charset().name()).append("\">\n")
            .append("<style>\n")
            .append("body {font-family: \"open sans\",sans-serif; margin-left: 20px;}\n")
            .append("h1 {font-weight: 300; line-height: 44px; margin: 25px 0 0 0;}\n")
            .append("h2 {font-size: 16px;font-weight: 300; line-height: 44px; margin: 0;}\n")
            .append("footer {font-weight: 300; line-height: 44px; margin-top: 10px;}\n")
            .append("hr {background-color: #f7f7f9;}\n")
            .append("div.trace {border:1px solid #e1e1e8; background-color: #f7f7f9;}\n")
            .append("p {padding-left: 20px;}\n")
            .append("p.tab {padding-left: 40px;}\n")
            .append("</style>\n")
            .append("<title>\n")
            .append(status).append(" ").append(reason)
            .append("\n</title>\n")
            .append("<body>\n")
            .append("<h1>").append(reason).append("</h1>\n")
            .append("<hr>");

        html.append("<h2>message: ").append(message).append("</h2>\n");
        html.append("<h2>status: ").append(status).append("</h2>\n");

        if (stacktrace != null) {
          html.append("<h2>stack:</h2>\n")
              .append("<div class=\"trace\">\n");

          Arrays.stream(stacktrace).forEach(line -> {
            html.append("<p class=\"line");
            if (line.startsWith("\t")) {
              html.append(" tab");
            }
            html.append("\">")
                .append("<code>")
                .append(line.replace("\t", "  "))
                .append("</code>")
                .append("</p>\n");
          });
          html.append("</div>\n");
        }

        html.append("</body>\n")
            .append("</html>\n");

        ctx.type(MediaType.html)
            .send(html.toString());
      }
    }

  }

  @Override
  public String name() {
    return "defaultErr";
  }

}
