package ab.issue.model.values;

import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.ForeignKey;
import android.arch.persistence.room.Index;
import android.arch.persistence.room.PrimaryKey;
import android.content.Context;
import android.support.annotation.Nullable;

import com.google.common.base.MoreObjects;
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode;
import com.google.zxing.client.result.CalendarParsedResult;

import net.fortuna.ical4j.model.property.Description;
import net.fortuna.ical4j.model.property.DtEnd;
import net.fortuna.ical4j.model.property.DtStart;
import net.fortuna.ical4j.model.property.Location;
import net.fortuna.ical4j.model.property.Organizer;
import net.fortuna.ical4j.model.property.Status;
import net.fortuna.ical4j.model.property.Summary;
import net.fortuna.ical4j.model.property.Version;

import org.joda.time.DateTime;

import java.net.URISyntaxException;
import java.util.List;

import javax.annotation.Nonnull;

import ab.issue.db.BarcodeDatabase;
import ab.issue.db.DbConstants;
import ab.issue.model.Barcode;
import ab.issue.utils.JodaUtils;
import androidx.navigation.NavController;
import timber.log.Timber;

@SuppressWarnings("Guava")
@Entity(
        tableName = DbConstants.CALENDAR_EVENT_TABLE_NAME,
        foreignKeys = @ForeignKey(
                entity = Barcode.class,
                parentColumns = DbConstants.COLUMN_NAME_BARCODE_ID,
                childColumns = DbConstants.COLUMN_NAME_EVENT_BARCODE_ID,
                onUpdate = ForeignKey.CASCADE,
                onDelete = ForeignKey.CASCADE
        ),
        indices = @Index(value = DbConstants.COLUMN_NAME_EVENT_BARCODE_ID, unique = true)
)
public class CalendarEventBarcodeFormat implements BarcodeFormatValue {


    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_ID)
    private long id;

    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_BARCODE_ID)
    private long barcodeId;

    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_SUMMARY)
    private String summary;

    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_START_TIME)
    private DateTime start;

    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_END_TIME)
    private DateTime end;

    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_STATUS)
    private String status;

    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_LOCATION)
    private String location;

    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_ORGANIZER)
    private String organizer;

    @ColumnInfo(name = DbConstants.COLUMN_NAME_EVENT_DESCRIPTION)
    private String description;

    public static CalendarEventBarcodeFormat create(@Nullable FirebaseVisionBarcode.CalendarEvent calendarEvent) {
        CalendarEventBarcodeFormat result = new CalendarEventBarcodeFormat();
        if (calendarEvent != null) {
            result.summary = calendarEvent.getSummary();
            result.start = JodaUtils.create(calendarEvent.getStart());
            result.end = JodaUtils.create(calendarEvent.getEnd());
            result.status = calendarEvent.getStatus();
            result.location = calendarEvent.getLocation();
            result.organizer = calendarEvent.getOrganizer();
            result.description = calendarEvent.getDescription();
        }
        return result;
    }

    public static CalendarEventBarcodeFormat create(CalendarParsedResult calendarParsedResult) {
        CalendarEventBarcodeFormat result = new CalendarEventBarcodeFormat();
        if (calendarParsedResult != null) {
            result.description = calendarParsedResult.getDescription();
            result.organizer = calendarParsedResult.getOrganizer();
            result.location = calendarParsedResult.getLocation();
            result.start = new DateTime(calendarParsedResult.getStartTimestamp());
            result.end = new DateTime(calendarParsedResult.getEndTimestamp());
            result.summary = calendarParsedResult.getSummary();
        }
        return result;
    }

    public CalendarEventBarcodeFormat() {
    }

    @Override
    public String encode() {
        net.fortuna.ical4j.model.Calendar calendar = new net.fortuna.ical4j.model.Calendar();
        calendar.getProperties().add(Version.VERSION_2_0);
        calendar.getProperties().add(new Summary(summary));
        calendar.getProperties().add(new DtStart(new net.fortuna.ical4j.model.DateTime(start.toDate())));
        calendar.getProperties().add(new DtEnd(new net.fortuna.ical4j.model.DateTime(end.toDate())));
        if (description != null) {
            calendar.getProperties().add(new Description(description));
        }
        if (location != null) {
            calendar.getProperties().add(new Location(location));
        }
        if (status != null) {
            calendar.getProperties().add(new Status(status));
        }
        if (organizer != null) {
            try {
                calendar.getProperties().add(new Organizer(organizer));
            } catch (URISyntaxException e) {
                Timber.e(e);
            }
        }
        return calendar.toString();
    }

    @Override
    public String getName(Context context) {
        return null;
    }

    @Override
    public BarcodeFormatValueType getType() {
        return BarcodeFormatValueType.CALENDAR_EVENT;
    }

    @Nonnull
    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("summary", summary)
                .add("start", start)
                .add("end", end)
                .add("status", status)
                .add("organizer", organizer)
                .add("location", location)
                .add("description", description)
                .add("barcodeId", barcodeId)
                .add("id", id)
                .omitNullValues()
                .toString();
    }

    @Override
    public int getIcon() {
        return 0;
    }

    @Override
    public void setBarcodeId(long barcodeId) {
        this.barcodeId = barcodeId;
    }

    @Override
    public void save(BarcodeDatabase barcodeDatabase) {
        barcodeDatabase.calendarEventDao().insert(this);
    }

    @Override
    public void create(NavController navController) {
//        navController.navigate(R.id.actionCreateCalendarEventBarcode);
    }

    @Override
    public List<Barcode> search(BarcodeDatabase barcodeDatabase, String query) {
        return barcodeDatabase.calendarEventDao().findTextInBarcodeFormatValues(query);
    }

    public long getBarcodeId() {
        return barcodeId;
    }

    public long getId() {
        return id;
    }

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

    public String getSummary() {
        return summary;
    }

    public DateTime getStart() {
        return start;
    }

    public DateTime getEnd() {
        return end;
    }

    public String getStatus() {
        return status;
    }

    public String getLocation() {
        return location;
    }

    public String getOrganizer() {
        return organizer;
    }

    public String getDescription() {
        return description;
    }

    public void setSummary(String summary) {
        this.summary = summary;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public void setOrganizer(String organizer) {
        this.organizer = organizer;
    }

    public void setEnd(DateTime end) {
        this.end = end;
    }

    public void setStart(DateTime start) {
        this.start = start;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

