package org.fdroid.fdroid.data;

import android.content.ContentValues;
import android.database.Cursor;
import android.text.TextUtils;

import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.Schema.RepoTable.Cols;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;

public class Repo extends ValueObject {

    public static final int VERSION_DENSITY_SPECIFIC_ICONS = 11;

    protected long id;

    public String address;
    public String name;
    public String description;
    /** index version, i.e. what fdroidserver built it - 0 if not specified */
    public int version;
    public boolean inuse;
    public int priority;
    /** The signing certificate, {@code null} for a newly added repo */
    public String signingCertificate;
    /**
     * The SHA1 fingerprint of {@link #signingCertificate}, set to {@code null} when a
     * newly added repo did not include fingerprint. It should never be an
     * empty {@link String}, i.e. {@code ""} */
    public String fingerprint;
    /** maximum age of index that will be accepted - 0 for any */
    public int maxage;
    /** last etag we updated from, null forces update */
    public String lastetag;
    public Date lastUpdated;
    public boolean isSwap;

    public String username;
    public String password;

    /** When the signed repo index was generated, used to protect against replay attacks */
    public long timestamp;

    public Repo() {
    }

    public Repo(Cursor cursor) {

        checkCursorPosition(cursor);

        for (int i = 0; i < cursor.getColumnCount(); i++) {
            switch (cursor.getColumnName(i)) {
                case Cols._ID:
                    id = cursor.getInt(i);
                    break;
                case Cols.LAST_ETAG:
                    lastetag = cursor.getString(i);
                    break;
                case Cols.ADDRESS:
                    address = cursor.getString(i);
                    break;
                case Cols.DESCRIPTION:
                    description = cursor.getString(i);
                    break;
                case Cols.FINGERPRINT:
                    fingerprint = cursor.getString(i);
                    break;
                case Cols.IN_USE:
                    inuse = cursor.getInt(i) == 1;
                    break;
                case Cols.LAST_UPDATED:
                    lastUpdated = Utils.parseTime(cursor.getString(i), null);
                    break;
                case Cols.MAX_AGE:
                    maxage = cursor.getInt(i);
                    break;
                case Cols.VERSION:
                    version = cursor.getInt(i);
                    break;
                case Cols.NAME:
                    name = cursor.getString(i);
                    break;
                case Cols.SIGNING_CERT:
                    signingCertificate = cursor.getString(i);
                    break;
                case Cols.PRIORITY:
                    priority = cursor.getInt(i);
                    break;
                case Cols.IS_SWAP:
                    isSwap = cursor.getInt(i) == 1;
                    break;
                case Cols.USERNAME:
                    username = cursor.getString(i);
                    break;
                case Cols.PASSWORD:
                    password = cursor.getString(i);
                    break;
                case Cols.TIMESTAMP:
                    timestamp = cursor.getLong(i);
                    break;
            }
        }
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return address;
    }

    public boolean isSigned() {
        return !TextUtils.isEmpty(this.signingCertificate);
    }

    /**
     * This happens when a repo is configed with a fingerprint, but the client
     * has not connected to it yet to download its signing certificate
     */
    public boolean isSignedButUnverified() {
        return TextUtils.isEmpty(this.signingCertificate) && !TextUtils.isEmpty(this.fingerprint);
    }

    public boolean hasBeenUpdated() {
        return this.lastetag != null;
    }

    /**
     * If we haven't run an update for this repo yet, then the name
     * will be unknown, in which case we will just take a guess at an
     * appropriate name based on the url (e.g. "f-droid.org/archive")
     */
    public static String addressToName(String address) {
        String tempName;
        try {
            URL url = new URL(address);
            tempName = url.getHost() + url.getPath();
        } catch (MalformedURLException e) {
            tempName = address;
        }
        return tempName;
    }

    private static int toInt(Integer value) {
        if (value == null) {
            return 0;
        }
        return value;
    }

    public void setValues(ContentValues values) {

        if (values.containsKey(Cols._ID)) {
            id = toInt(values.getAsInteger(Cols._ID));
        }

        if (values.containsKey(Cols.LAST_ETAG)) {
            lastetag = values.getAsString(Cols.LAST_ETAG);
        }

        if (values.containsKey(Cols.ADDRESS)) {
            address = values.getAsString(Cols.ADDRESS);
        }

        if (values.containsKey(Cols.DESCRIPTION)) {
            description = values.getAsString(Cols.DESCRIPTION);
        }

        if (values.containsKey(Cols.FINGERPRINT)) {
            fingerprint = values.getAsString(Cols.FINGERPRINT);
        }

        if (values.containsKey(Cols.IN_USE)) {
            inuse = toInt(values.getAsInteger(Cols.IN_USE)) == 1;
        }

        if (values.containsKey(Cols.LAST_UPDATED)) {
            final String dateString = values.getAsString(Cols.LAST_UPDATED);
            lastUpdated = Utils.parseTime(dateString, null);
        }

        if (values.containsKey(Cols.MAX_AGE)) {
            maxage = toInt(values.getAsInteger(Cols.MAX_AGE));
        }

        if (values.containsKey(Cols.VERSION)) {
            version = toInt(values.getAsInteger(Cols.VERSION));
        }

        if (values.containsKey(Cols.NAME)) {
            name = values.getAsString(Cols.NAME);
        }

        if (values.containsKey(Cols.SIGNING_CERT)) {
            signingCertificate = values.getAsString(Cols.SIGNING_CERT);
        }

        if (values.containsKey(Cols.PRIORITY)) {
            priority = toInt(values.getAsInteger(Cols.PRIORITY));
        }

        if (values.containsKey(Cols.IS_SWAP)) {
            isSwap = toInt(values.getAsInteger(Cols.IS_SWAP)) == 1;
        }

        if (values.containsKey(Cols.USERNAME)) {
            username = values.getAsString(Cols.USERNAME);
        }

        if (values.containsKey(Cols.PASSWORD)) {
            password = values.getAsString(Cols.PASSWORD);
        }

        if (values.containsKey(Cols.TIMESTAMP)) {
            timestamp = toInt(values.getAsInteger(Cols.TIMESTAMP));
        }
    }
}
