package calhoun.gebo.internal.db;

import java.util.List;

import calhoun.bean.AlignmentSegment;
import calhoun.gebo.model.Alignment;
import calhoun.gebo.model.Property;
import calhoun.gebo.model.Segment;
import calhoun.gebo.model.SimpleSegment;
import calhoun.gebo.util.Informer;
import calhoun.gebo.util.Q;
import calhoun.util.DbSession;

public class CalhounAlignment extends Alignment {

    private static Informer I = new Informer(CalhounAlignment.class);

    public CalhounAlignment(Segment xSeg, Segment ySeg, Property[] properties) {
        super(null, xSeg, ySeg, properties);
        // if (getQueryFeatureId() == null) {
        // // I.warn("query feture id is null");
        // I.warn("query feature id is null! Ref feature id: "
        // + getReferenceFeatureId());
        // // for (Property p : getProperties()) {
        // // I.warn("print: " + p);
        // // }
        // } else {
        // // I.warn("ok...");
        // }
    }

    public boolean isGapped(){
	return false;
    }

    public Segment getReferenceSegmentForQuery(Segment subQuery) {
        // if ( getQueryFeatureId() == null){
        // return super.getReferenceSegmentForQuery(subQuery);

        // }
        // I.warn("a");
        int queryA = subQuery.getStart() > getQuery().getStart() ? subQuery
                .getStart() : getQuery().getStart();
        // I.warn("b");
        int queryZ = subQuery.getStop() < getQuery().getStop() ? subQuery
                .getStop() : getQuery().getStop();
        // I.warn("c");

        calhoun.bean.AlignmentSegment qSegmentA = getAlignmentSegmentAt(
                getReferenceFeatureId(), queryA, true);
        // I.warn("d");
        calhoun.bean.AlignmentSegment qSegmentZ = getAlignmentSegmentAt(
                getReferenceFeatureId(), queryZ, true);

        // calhoun.bean.AlignmentSegment qSegmentA = getAlignmentSegmentAt(
        // getQueryFeatureId(), queryA);
        // I.warn("d");
        // calhoun.bean.AlignmentSegment qSegmentZ = getAlignmentSegmentAt(
        // getQueryFeatureId(), queryZ);
        // if (qSegmentA != null && qSegmentZ != null) {
        // I.warn("e");
        int refA = qSegmentA.mapQueryToSequence(queryA);
        // I.warn("f");
        int refZ = qSegmentZ.mapQueryToSequence(queryZ);
        // I.warn("g");
        return new SimpleSegment(getReference().getSequence(), refA, refZ);
        // } else {
        // return new SimpleSegment(getReference());
        // }
    }

    // public String getQueryFeatureId() {
    // return getPropertyValue("ALT_FEATURE_ID");
    // }

    public String getReferenceFeatureId() {
        return getPropertyValue("FEATURE_ID");
    }

    public Segment getQuerySegmentForReference(Segment subReference) {
        int referenceA = subReference.getStart() > getReference().getStart() ? subReference
                .getStart()
                : getReference().getStart();
        int referenceZ = subReference.getStop() < getReference().getStop() ? subReference
                .getStop()
                : getReference().getStop();
        calhoun.bean.AlignmentSegment rSegmentA = getAlignmentSegmentAt(
                getReferenceFeatureId(), referenceA, false);
        calhoun.bean.AlignmentSegment rSegmentZ = getAlignmentSegmentAt(
                getReferenceFeatureId(), referenceZ, false);
        // if (qSegmentA == null) {
        // qSegmentA = getAlignmentSegmentAt(getReferenceFeatureId(),
        // getReference().getStart());
        // }
        // if (qSegmentZ == null) {
        // qSegmentZ = getAlignmentSegmentAt(getReferenceFeatureId(),
        // getReference().getStop());
        // }
        int queryA = rSegmentA.getStart();
        int queryZ = rSegmentZ.getStop();
        try {
            queryA = rSegmentA.mapSequenceToQuery(referenceA);
        } catch (Throwable t) {}
        try {
            queryZ = rSegmentZ.mapSequenceToQuery(referenceZ);
        } catch (Throwable t) {
            I.warn("error mapping ref to query");
        }
        return new SimpleSegment(getQuery().getSequence(), queryA, queryZ);
    }

    public static calhoun.bean.AlignmentSegment getAlignmentSegmentAt(
            String spanId, int base, boolean isQuery) {
        if (spanId == null) {
            I.warn("null span id!");
            return null;
        }
        String startCol = isQuery ? "queryStart" : "start";
        String stopCol = isQuery ? "queryStop" : "stop";
        DbSession s = CalhounConnectionManager.getInstance().getDbSession();
        String hql = "from AlignmentSegment a where a.span.id = " + spanId
                + " and a." + startCol + "<= " + base + " and a." + stopCol
                + ">= " + base;
        // I.warn("AlignmentTrack: " + getQuery());
        I.warn("hql: " + hql);
        try {
            Q.startStopWatch(hql);
            List rows = s.find(hql);
            for (Object o : rows) {
                AlignmentSegment as = (AlignmentSegment) o;
                // I.warn("AlignmentSegment: " + as.getId() + ": " +
                // as.getStart()
                // + "-" + as.getStop());
                Q.stopStopWatch(hql);
                return as;
            }
        } catch (Throwable t) {
            I
                    .error(
                            "Error retrieving corresponding alignment segment from database",
                            t);
        }
        return null;
    }

}
