package de.fhg.iais.cortex.jobscheduler.crawler.hibernate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.apache.http.HttpStatus;
import org.codehaus.jackson.annotate.JsonPropertyOrder;

import de.fhg.iais.commons.hibernate.IDatabaseObject;

@JsonPropertyOrder({
    "crawlerStatsName",
    "totalProcessedPages",
    "totalIndexedDocuments",
    "totalLinks",
    "totalTextSize",
    "httpCodeOk",
    "httpCodeNotFound",
    "httpCodeNotModified",
    "httpCodeServerError",
    "httpCodeHttpError",
    "httpCodeOther",
    "errorCount"
})
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "crawlerStatsName",
    "totalProcessedPages",
    "totalIndexedDocuments",
    "totalLinks",
    "totalTextSize",
    "httpCodeOk",
    "httpCodeNotFound",
    "httpCodeNotModified",
    "httpCodeServerError",
    "httpCodeHttpError",
    "httpCodeOther",
    "errorCount"
})
@XmlRootElement(name = "AscCrawlerStats")
@Entity
@Table(name = "asc_crawler_stats")
public class WebsiteCrawlerStats implements IDatabaseObject {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "crawler_stats_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @XmlElement(name = "crawlerStatsName")
    @Column(unique = true, name = "crawler_stats_name", nullable = false)
    private String name;

    @XmlElement(name = "startTime")
    @Column(name = "start_time", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long timeStarted;

    @XmlElement(name = "endTime")
    @Column(name = "end_time", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long timeEnded;

    @XmlElement(name = "duration")
    @Column(name = "duration", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long duration;

    @XmlElement(name = "totalLinks")
    @Column(name = "total_links", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long totalLinks;

    @XmlElement(name = "totalTextSize")
    @Column(name = "total_text_size", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long totalTextSize;

    @XmlElement(name = "totalProcessedPages")
    @Column(name = "total_processed_pages", columnDefinition = "INTEGER DEFAULT 0", nullable = false)
    private Integer totalProcessedPages;

    @XmlElement(name = "totalIndexedDocuments")
    @Column(name = "total_indexed_documents", columnDefinition = "INTEGER DEFAULT 0", nullable = false)
    private Integer totalIndexedDocuments;

    @XmlElement(name = "httpCodeOk")
    @Column(name = "http_code_ok", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long httpCodeOk;

    @XmlElement(name = "httpCodeNotFound")
    @Column(name = "http_code_not_found", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long httpCodeNotFound;

    @XmlElement(name = "httpCodeNotModified")
    @Column(name = "http_code_not_modified", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long httpCodeNotModified;

    @XmlElement(name = "httpCodeServerError")
    @Column(name = "http_code_server_error", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long httpCodeServerError;

    @XmlElement(name = "httpCodeHttpError")
    @Column(name = "http_code_http_error", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long httpCodeHttpError;

    @XmlElement(name = "httpCodeOther")
    @Column(name = "http_code_other", columnDefinition = "BIGINT DEFAULT 0", nullable = false)
    private Long httpCodeOther;

    @XmlElement(name = "errorCount")
    @Column(name = "error_count", columnDefinition = "INTEGER DEFAULT 0", nullable = false)
    private Integer errorCount;

    public WebsiteCrawlerStats() {
        this.name = "";
        this.timeStarted = 0L;
        this.timeEnded = 0L;
        this.duration = 0L;
        this.totalLinks = 0L;
        this.totalTextSize = 0L;
        this.totalProcessedPages = 0;
        this.totalIndexedDocuments = 0;
        this.httpCodeHttpError = 0L;
        this.httpCodeNotFound = 0L;
        this.httpCodeNotModified = 0L;
        this.httpCodeOk = 0L;
        this.httpCodeServerError = 0L;
        this.httpCodeOther = 0L;
        this.errorCount = 0;
    }

    @Override
    public long getId() {
        return this.id;
    }

    @Override
    public void setId(long id) {
        this.id = id;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    public Long getTimeStarted() {
        return this.timeStarted;
    }

    public void setTimeStarted(Long timeStarted) {
        this.timeStarted = timeStarted;
    }

    public Long getTimeEnded() {
        return this.timeEnded;
    }

    public void setTimeEnded(Long timeEnded) {
        this.timeEnded = timeEnded;
    }

    public Long getDuration() {
        return this.duration;
    }

    public void setDuration(Long duration) {
        this.duration = duration;
    }

    public Integer getTotalProcessedPages() {
        return this.totalProcessedPages;
    }

    public void setTotalProcessedPages(Integer totalProcessedPages) {
        this.totalProcessedPages = totalProcessedPages;
    }

    public Integer getTotalIndexedDocuments() {
        return this.totalIndexedDocuments;
    }

    public void setTotalIndexedDocuments(Integer totalIndexedDocuments) {
        this.totalIndexedDocuments = totalIndexedDocuments;
    }

    public Long getTotalLinks() {
        return this.totalLinks;
    }

    public void setTotalLinks(Long totalLinks) {
        this.totalLinks = totalLinks;
    }

    public Long getTotalTextSize() {
        return this.totalTextSize;
    }

    public void setTotalTextSize(Long totalTextSize) {
        this.totalTextSize = totalTextSize;
    }

    public Long getHttpCodeOk() {
        return this.httpCodeOk;
    }

    public void setHttpCodeOk(Long httpCodeOk) {
        this.httpCodeOk = httpCodeOk;
    }

    public Long getHttpCodeNotFound() {
        return this.httpCodeNotFound;
    }

    public void setHttpCodeNotFound(Long httpCodeNotFound) {
        this.httpCodeNotFound = httpCodeNotFound;
    }

    public Long getHttpCodeNotModified() {
        return this.httpCodeNotModified;
    }

    public void setHttpCodeNotModified(Long httpCodeNotModified) {
        this.httpCodeNotModified = httpCodeNotModified;
    }

    public Long getHttpCodeServerError() {
        return this.httpCodeServerError;
    }

    public void setHttpCodeServerError(Long httpCodeServerError) {
        this.httpCodeServerError = httpCodeServerError;
    }

    public Long getHttpCodeHttpError() {
        return this.httpCodeHttpError;
    }

    public void setHttpCodeHttpError(Long httpCodeHttpError) {
        this.httpCodeHttpError = httpCodeHttpError;
    }

    public Long getHttpCodeOther() {
        return this.httpCodeOther;
    }

    public void setHttpCodeOther(Long httpCodeOther) {
        this.httpCodeOther = httpCodeOther;
    }

    public Integer getErrorCount() {
        return this.errorCount;
    }

    public void setErrorCount(Integer errorCount) {
        this.errorCount = errorCount;
    }

    public void incTotalLinks(Integer count) {
        this.totalLinks += count;
    }

    public void incTotalTextSize(Integer count) {
        this.totalTextSize += count;
    }

    public void incProcessedPages() {
        this.totalProcessedPages++;
    }

    public void incTotalIndexedDocuments() {
        this.totalIndexedDocuments++;
    }

    public void incHttpCode(Integer httpCode) {
        switch ( httpCode ) {
            case HttpStatus.SC_OK: {
                this.httpCodeOk++;
                break;
            }
            case HttpStatus.SC_NOT_FOUND: {
                this.httpCodeNotFound++;
                break;
            }
            case HttpStatus.SC_NOT_MODIFIED: {
                this.httpCodeNotModified++;
                break;
            }
            case HttpStatus.SC_INTERNAL_SERVER_ERROR: {
                this.httpCodeServerError++;
                break;
            }
            default: {
                if ( httpCode > 999 ) {
                    this.httpCodeHttpError++;
                } else {
                    this.httpCodeOther++;
                }
            }
        }
    }

    public void incErrorCount() {
        this.errorCount++;
    }

    public void reset() {
        this.setDuration(0L);
        this.setErrorCount(0);
        this.setHttpCodeHttpError(0L);
        this.setHttpCodeNotFound(0L);
        this.setHttpCodeNotModified(0L);
        this.setHttpCodeOk(0L);
        this.setHttpCodeServerError(0L);
        this.setHttpCodeOther(0L);
        this.setTimeEnded(0L);
        this.setTimeStarted(0L);
        this.setTotalLinks(0L);
        this.setTotalProcessedPages(0);
        this.setTotalIndexedDocuments(0);
        this.setTotalTextSize(0L);
    }

    public WebsiteCrawlerStats copy() {
        WebsiteCrawlerStats newStats = new WebsiteCrawlerStats();

        newStats.setTimeEnded(this.timeEnded);
        newStats.setTimeStarted(this.timeStarted);
        newStats.setDuration(this.duration);
        newStats.setTotalLinks(this.totalLinks);
        newStats.setTotalTextSize(this.totalTextSize);
        newStats.setTotalProcessedPages(this.totalProcessedPages);
        newStats.setTotalIndexedDocuments(this.totalIndexedDocuments);
        newStats.setHttpCodeHttpError(this.httpCodeHttpError);
        newStats.setHttpCodeNotFound(this.httpCodeNotFound);
        newStats.setHttpCodeNotModified(this.httpCodeNotModified);
        newStats.setHttpCodeOk(this.httpCodeOk);
        newStats.setHttpCodeServerError(this.httpCodeServerError);
        newStats.setHttpCodeOther(this.httpCodeOther);
        newStats.setErrorCount(this.errorCount);

        return newStats;
    }

    @Override
    public int hashCode() {
        final Integer prime = 31;
        Integer result = 1;
        result = (prime * result) + (int) (this.id ^ (this.id >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if ( this == obj ) {
            return true;
        }
        if ( obj == null ) {
            return false;
        }
        if ( getClass() != obj.getClass() ) {
            return false;
        }
        WebsiteCrawlerStats other = (WebsiteCrawlerStats) obj;
        if ( this.id != other.id ) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "AscCrawlerStats [id="
            + this.id
            + ", name="
            + this.name
            + ", timeStarted="
            + this.timeStarted
            + ", timeEnded="
            + this.timeEnded
            + ", duration="
            + this.duration
            + ", totalLinks="
            + this.totalLinks
            + ", totalTextSize="
            + this.totalTextSize
            + ", totalProcessedPages="
            + this.totalProcessedPages
            + ", totalIndexedDocuments="
            + this.totalIndexedDocuments
            + ", httpCodeOk="
            + this.httpCodeOk
            + ", httpCodeNotFound="
            + this.httpCodeNotFound
            + ", httpCodeNotModified="
            + this.httpCodeNotModified
            + ", httpCodeServerError="
            + this.httpCodeServerError
            + ", httpCodeHttpError="
            + this.httpCodeHttpError
            + ", httpCodeOther="
            + this.httpCodeOther
            + ", errorCount="
            + this.errorCount
            + "]";
    }
}
