package ch.threema.storage.factories;

import android.content.ContentValues;

import android.database.Cursor;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import ch.threema.storage.CursorHelper;
import ch.threema.storage.DatabaseCreationProvider;
import ch.threema.storage.DatabaseProvider;
import ch.threema.storage.DatabaseUtil;
import ch.threema.storage.models.DistributionListMemberModel;

public class DistributionListMemberModelFactory extends ModelFactory {

    public DistributionListMemberModelFactory(DatabaseProvider databaseProvider) {
        super(databaseProvider, DistributionListMemberModel.TABLE);
    }

    public DistributionListMemberModel getByDistributionListIdAndIdentity(long distributionListId, String identity) {
        if (identity == null) {
            return null;
        }

        return getFirst(
            DistributionListMemberModel.COLUMN_DISTRIBUTION_LIST_ID + "=? "
                + " AND " + DistributionListMemberModel.COLUMN_IDENTITY + "=?",
            new String[]{
                String.valueOf(distributionListId),
                identity
            });
    }

    public List<DistributionListMemberModel> getByDistributionListId(long distributionListId) {
        return convertList(getReadableDatabase().query(this.getTableName(),
            null,
            DistributionListMemberModel.COLUMN_DISTRIBUTION_LIST_ID + "=?",
            new String[]{
                String.valueOf(distributionListId)
            },
            null,
            null,
            null));
    }

    private DistributionListMemberModel convert(Cursor cursor) {
        if (cursor != null && cursor.getPosition() >= 0) {
            final DistributionListMemberModel distributionListMemberModel = new DistributionListMemberModel();
            new CursorHelper(cursor, getColumnIndexCache()).current(new CursorHelper.Callback() {
                @Override
                public boolean next(CursorHelper cursorHelper) {
                    distributionListMemberModel
                        .setId(cursorHelper.getInt(DistributionListMemberModel.COLUMN_ID))
                        .setDistributionListId(cursorHelper.getInt(DistributionListMemberModel.COLUMN_DISTRIBUTION_LIST_ID))
                        .setIdentity(cursorHelper.getString(DistributionListMemberModel.COLUMN_IDENTITY))
                        .setActive(cursorHelper.getBoolean(DistributionListMemberModel.COLUMN_IS_ACTIVE));
                    return false;
                }
            });

            return distributionListMemberModel;
        }

        return null;
    }

    private List<DistributionListMemberModel> convertList(Cursor c) {
        List<DistributionListMemberModel> result = new ArrayList<>();
        if (c != null) {
            try {
                while (c.moveToNext()) {
                    result.add(convert(c));
                }
            } finally {
                c.close();
            }
        }
        return result;
    }

    public boolean createOrUpdate(DistributionListMemberModel distributionListMemberModel) {
        boolean insert = true;
        if (distributionListMemberModel.getId() > 0) {
            Cursor cursor = getReadableDatabase().query(
                this.getTableName(),
                null,
                DistributionListMemberModel.COLUMN_ID + "=?",
                new String[]{
                    String.valueOf(distributionListMemberModel.getId())
                },
                null,
                null,
                null
            );

            if (cursor != null) {
                try {
                    insert = !cursor.moveToNext();
                } finally {
                    cursor.close();
                }
            }
        }

        if (insert) {
            return create(distributionListMemberModel);
        } else {
            return update(distributionListMemberModel);
        }
    }

    private ContentValues buildContentValues(DistributionListMemberModel distributionListMemberModel) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(DistributionListMemberModel.COLUMN_DISTRIBUTION_LIST_ID, distributionListMemberModel.getDistributionListId());
        contentValues.put(DistributionListMemberModel.COLUMN_IDENTITY, distributionListMemberModel.getIdentity());
        contentValues.put(DistributionListMemberModel.COLUMN_IS_ACTIVE, distributionListMemberModel.isActive());
        return contentValues;
    }

    public boolean create(DistributionListMemberModel distributionListMemberModel) {
        ContentValues contentValues = buildContentValues(distributionListMemberModel);
        long newId = getWritableDatabase().insertOrThrow(this.getTableName(), null, contentValues);
        if (newId > 0) {
            distributionListMemberModel.setId((int) newId);
            return true;
        }
        return false;
    }

    public boolean update(DistributionListMemberModel distributionListMemberModel) {
        ContentValues contentValues = buildContentValues(distributionListMemberModel);
        getWritableDatabase().update(this.getTableName(),
            contentValues,
            DistributionListMemberModel.COLUMN_ID + "=?",
            new String[]{
                String.valueOf(distributionListMemberModel.getId())
            });
        return true;
    }

    private DistributionListMemberModel getFirst(String selection, String[] selectionArgs) {
        Cursor cursor = getReadableDatabase().query(
            this.getTableName(),
            null,
            selection,
            selectionArgs,
            null,
            null,
            null
        );

        if (cursor != null) {
            try {
                if (cursor.moveToFirst()) {
                    return convert(cursor);
                }
            } finally {
                cursor.close();
            }
        }

        return null;
    }

    public int deleteByDistributionListId(long distributionListId) {
        return getWritableDatabase().delete(this.getTableName(),
            DistributionListMemberModel.COLUMN_DISTRIBUTION_LIST_ID + "=?",
            new String[]{
                String.valueOf(distributionListId)
            });
    }

    public int delete(List<DistributionListMemberModel> modelsToRemove) {
        String[] args = new String[modelsToRemove.size()];
        for (int n = 0; n < modelsToRemove.size(); n++) {
            args[n] = String.valueOf(modelsToRemove.get(n).getId());
        }
        return getWritableDatabase().delete(this.getTableName(),
            DistributionListMemberModel.COLUMN_ID + " IN (" + DatabaseUtil.makePlaceholders(args.length) + ")",
            args);
    }

    public static class Creator implements DatabaseCreationProvider {
        @Override
        @NonNull
        public String [] getCreationStatements() {
            return new String[]{
                "CREATE TABLE `" + DistributionListMemberModel.TABLE + "`(" +
                    "`" + DistributionListMemberModel.COLUMN_ID + "` INTEGER PRIMARY KEY AUTOINCREMENT , " +
                    "`" + DistributionListMemberModel.COLUMN_IDENTITY + "` VARCHAR , " +
                    "`" + DistributionListMemberModel.COLUMN_DISTRIBUTION_LIST_ID + "` INTEGER , " +
                    "`" + DistributionListMemberModel.COLUMN_IS_ACTIVE + "` SMALLINT NOT NULL" +
                    ")",

                "CREATE INDEX `distribution_list_member_dis_idx`" +
                    " ON `" + DistributionListMemberModel.TABLE + "`(`" + DistributionListMemberModel.COLUMN_DISTRIBUTION_LIST_ID + "`)"
            };
        }
    }
}
