/*
 * 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.apache.nutch.protocol;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;

import org.apache.hadoop.io.VersionMismatchException;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableUtils;

/**
 * @author Andrzej Bialecki
 */
public class ProtocolStatus implements Writable {

  private final static byte VERSION = 2;

  /** Content was retrieved without errors. */
  public static final int SUCCESS = 1;
  /** Content was not retrieved. Any further errors may be indicated in args. */
  public static final int FAILED = 2;

  /** This protocol was not found. Application may attempt to retry later. */
  public static final int PROTO_NOT_FOUND = 10;
  /** Resource is gone. */
  public static final int GONE = 11;
  /** Resource has moved permanently. New url should be found in args. */
  public static final int MOVED = 12;
  /** Resource has moved temporarily. New url should be found in args. */
  public static final int TEMP_MOVED = 13;
  /** Resource was not found. */
  public static final int NOTFOUND = 14;
  /** Temporary failure. Application may retry immediately. */
  public static final int RETRY = 15;
  /**
   * Unspecified exception occurred. Further information may be provided in args.
   */
  public static final int EXCEPTION = 16;
  /** Access denied - authorization required, but missing/incorrect. */
  public static final int ACCESS_DENIED = 17;
  /** Access denied by robots.txt rules. */
  public static final int ROBOTS_DENIED = 18;
  /** Too many redirects. */
  public static final int REDIR_EXCEEDED = 19;
  /** Not fetching. */
  public static final int NOTFETCHING = 20;
  /** Unchanged since the last fetch. */
  public static final int NOTMODIFIED = 21;
  /**
   * Request was refused by protocol plugins, because it would block. The
   * expected number of milliseconds to wait before retry may be provided in
   * args.
   */
  @Deprecated
  public static final int WOULDBLOCK = 22;
  /** Thread was blocked http.max.delays times during fetching. */
  @Deprecated
  public static final int BLOCKED = 23;

  // Useful static instances for status codes that don't usually require any
  // additional arguments.
  public static final ProtocolStatus STATUS_SUCCESS = new ProtocolStatus(
      SUCCESS);
  public static final ProtocolStatus STATUS_FAILED = new ProtocolStatus(FAILED);
  public static final ProtocolStatus STATUS_GONE = new ProtocolStatus(GONE);
  public static final ProtocolStatus STATUS_NOTFOUND = new ProtocolStatus(
      NOTFOUND);
  public static final ProtocolStatus STATUS_RETRY = new ProtocolStatus(RETRY);
  public static final ProtocolStatus STATUS_ROBOTS_DENIED = new ProtocolStatus(
      ROBOTS_DENIED);
  public static final ProtocolStatus STATUS_REDIR_EXCEEDED = new ProtocolStatus(
      REDIR_EXCEEDED);
  public static final ProtocolStatus STATUS_NOTFETCHING = new ProtocolStatus(
      NOTFETCHING);
  public static final ProtocolStatus STATUS_NOTMODIFIED = new ProtocolStatus(
      NOTMODIFIED);
  public static final ProtocolStatus STATUS_WOULDBLOCK = new ProtocolStatus(
      WOULDBLOCK);
  public static final ProtocolStatus STATUS_BLOCKED = new ProtocolStatus(
      BLOCKED);

  private int code;
  private long lastModified;
  private String[] args;

  private static final HashMap<Integer, String> codeToName = new HashMap<>();
  static {
    codeToName.put(Integer.valueOf(SUCCESS), "success");
    codeToName.put(Integer.valueOf(FAILED), "failed");
    codeToName.put(Integer.valueOf(PROTO_NOT_FOUND), "proto_not_found");
    codeToName.put(Integer.valueOf(GONE), "gone");
    codeToName.put(Integer.valueOf(MOVED), "moved");
    codeToName.put(Integer.valueOf(TEMP_MOVED), "temp_moved");
    codeToName.put(Integer.valueOf(NOTFOUND), "notfound");
    codeToName.put(Integer.valueOf(RETRY), "retry");
    codeToName.put(Integer.valueOf(EXCEPTION), "exception");
    codeToName.put(Integer.valueOf(ACCESS_DENIED), "access_denied");
    codeToName.put(Integer.valueOf(ROBOTS_DENIED), "robots_denied");
    codeToName.put(Integer.valueOf(REDIR_EXCEEDED), "redir_exceeded");
    codeToName.put(Integer.valueOf(NOTFETCHING), "notfetching");
    codeToName.put(Integer.valueOf(NOTMODIFIED), "notmodified");
    codeToName.put(Integer.valueOf(WOULDBLOCK), "wouldblock");
    codeToName.put(Integer.valueOf(BLOCKED), "blocked");
  }

  public ProtocolStatus() {

  }

  public ProtocolStatus(int code, String[] args) {
    this.code = code;
    this.args = args;
  }

  public ProtocolStatus(int code, String[] args, long lastModified) {
    this.code = code;
    this.args = args;
    this.lastModified = lastModified;
  }

  public ProtocolStatus(int code) {
    this(code, null);
  }

  public ProtocolStatus(int code, long lastModified) {
    this(code, null, lastModified);
  }

  public ProtocolStatus(int code, Object message) {
    this(code, message, 0L);
  }

  public ProtocolStatus(int code, Object message, long lastModified) {
    this.code = code;
    this.lastModified = lastModified;
    if (message != null)
      this.args = new String[] { String.valueOf(message) };
  }

  public ProtocolStatus(Throwable t) {
    this(EXCEPTION, t);
  }

  public static ProtocolStatus read(DataInput in) throws IOException {
    ProtocolStatus res = new ProtocolStatus();
    res.readFields(in);
    return res;
  }

  public void readFields(DataInput in) throws IOException {
    byte version = in.readByte();
    switch (version) {
    case 1:
      code = in.readByte();
      lastModified = in.readLong();
      args = WritableUtils.readCompressedStringArray(in);
      break;
    case VERSION:
      code = in.readByte();
      lastModified = in.readLong();
      args = WritableUtils.readStringArray(in);
      break;
    default:
      throw new VersionMismatchException(VERSION, version);
    }
  }

  public void write(DataOutput out) throws IOException {
    out.writeByte(VERSION);
    out.writeByte((byte) code);
    out.writeLong(lastModified);
    if (args == null) {
      out.writeInt(-1);
    } else {
      WritableUtils.writeStringArray(out, args);
    }
  }

  public void setArgs(String[] args) {
    this.args = args;
  }

  public String[] getArgs() {
    return args;
  }

  public int getCode() {
    return code;
  }

  public String getName() {
    return codeToName.get(this.code);
  }

  public void setCode(int code) {
    this.code = code;
  }

  public boolean isSuccess() {
    return code == SUCCESS;
  }

  public boolean isTransientFailure() {
    return code == ACCESS_DENIED || code == EXCEPTION || code == REDIR_EXCEEDED
        || code == RETRY || code == TEMP_MOVED || code == WOULDBLOCK
        || code == PROTO_NOT_FOUND;
  }

  public boolean isPermanentFailure() {
    return code == FAILED || code == GONE || code == MOVED || code == NOTFOUND
        || code == ROBOTS_DENIED;
  }

  public boolean isRedirect() {
      return code == MOVED || code == TEMP_MOVED;
  }

  public String getMessage() {
    if (args != null && args.length > 0)
      return args[0];
    return null;
  }

  public void setMessage(String msg) {
    if (args != null && args.length > 0)
      args[0] = msg;
    else
      args = new String[] { msg };
  }

  public long getLastModified() {
    return lastModified;
  }

  public void setLastModified(long lastModified) {
    this.lastModified = lastModified;
  }

  public boolean equals(Object o) {
    if (o == null)
      return false;
    if (!(o instanceof ProtocolStatus))
      return false;
    ProtocolStatus other = (ProtocolStatus) o;
    if (this.code != other.code || this.lastModified != other.lastModified)
      return false;
    if (this.args == null) {
      if (other.args == null)
        return true;
      else
        return false;
    } else {
      if (other.args == null)
        return false;
      if (other.args.length != this.args.length)
        return false;
      for (int i = 0; i < this.args.length; i++) {
        if (!this.args[i].equals(other.args[i]))
          return false;
      }
    }
    return true;
  }

  public String toString() {
    StringBuffer res = new StringBuffer();
    res.append(codeToName.get(Integer.valueOf(code)) + "(" + code
        + "), lastModified=" + lastModified);
    if (args != null) {
      if (args.length == 1) {
        res.append(": " + String.valueOf(args[0]));
      } else {
        for (int i = 0; i < args.length; i++) {
          if (args[i] != null)
            res.append(", args[" + i + "]=" + String.valueOf(args[i]));
        }
      }
    }
    return res.toString();
  }
}
