package com.atlassian.bitbucket.validation;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Maps.transformValues;

/**
 * Simple implementation of {@link FormErrors} as a plain Java object with a builder,
 */
public class SimpleFormErrors implements FormErrors {

    private final Map<String, Collection<String>> fieldErrors;
    private final Collection<String> formErrors;

    private SimpleFormErrors(Builder builder) {
        this.fieldErrors = copyFieldErrors(builder.fieldErrors);
        this.formErrors = builder.formErrors.build();
    }

    @Nonnull
    @Override
    public Collection<String> getErrors(@Nonnull String field) {
        Collection<String> forField = fieldErrors.get(field);
        return forField != null ? forField : Collections.<String>emptyList();
    }

    @Nonnull
    @Override
    public Map<String, Collection<String>> getFieldErrors() {
        return fieldErrors;
    }

    @Nonnull
    @Override
    public Collection<String> getFormErrors() {
        return formErrors;
    }

    @Override
    public boolean isEmpty() {
        return fieldErrors.isEmpty() && formErrors.isEmpty();
    }

    private Map<String, Collection<String>> copyFieldErrors(Map<String, ImmutableList.Builder<String>> fieldErrors) {
        return ImmutableMap.copyOf(transformValues(fieldErrors, ImmutableList.Builder<String>::build));
    }

    public static class Builder {

        private final Map<String, ImmutableList.Builder<String>> fieldErrors = Maps.newHashMap();
        private final ImmutableList.Builder<String> formErrors = ImmutableList.builder();

        public Builder fieldError(@Nonnull String field, @Nonnull String error) {
            return fieldErrors(field, error);
        }

        public Builder fieldErrors(@Nonnull String field, @Nonnull String error, @Nonnull String... moreErrors) {
            checkNotNull(field, "field");
            checkNotNull(error, "error");
            checkNotNull(moreErrors, "moreErrors");
            if (!fieldErrors.containsKey(field)) {
                fieldErrors.put(field, ImmutableList.<String>builder());
            }
            fieldErrors.get(field).add(error).add(moreErrors);
            return this;
        }

        public Builder formError(@Nonnull String error) {
            return formErrors(error);
        }

        public Builder formErrors(@Nonnull String error, @Nonnull String... moreErrors) {
            checkNotNull(error, "error");
            checkNotNull(moreErrors, "moreErrors");
            this.formErrors.add(error).add(moreErrors);
            return this;
        }

        public SimpleFormErrors build() {
            return new SimpleFormErrors(this);
        }
    }
}
