/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.hugegraph.structure;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Supplier;

import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.id.EdgeId;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.IdGenerator;
import org.apache.hugegraph.backend.serializer.BytesBuffer;
import org.apache.hugegraph.backend.tx.GraphTransaction;
import org.apache.hugegraph.perf.PerfUtil.Watched;
import org.apache.hugegraph.schema.PropertyKey;
import org.apache.hugegraph.schema.SchemaLabel;
import org.apache.hugegraph.schema.VertexLabel;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.Idfiable;
import org.apache.hugegraph.type.define.Cardinality;
import org.apache.hugegraph.type.define.HugeKeys;
import org.apache.hugegraph.util.CollectionUtil;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.InsertionOrderUtil;
import org.apache.hugegraph.util.collection.CollectionFactory;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
import org.eclipse.collections.api.iterator.IntIterator;
import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;

public abstract class HugeElement implements Element, GraphType, Idfiable, Comparable<HugeElement> {

    private static final MutableIntObjectMap<HugeProperty<?>> EMPTY_MAP =
            CollectionFactory.newIntObjectMap();
    private static final int MAX_PROPERTIES = BytesBuffer.UINT16_MAX;

    private final HugeGraph graph;
    private MutableIntObjectMap<HugeProperty<?>> properties;
    // TODO: move into properties to keep small object
    private long expiredTime;

    private boolean removed;
    private boolean fresh;
    private boolean propLoaded;
    private boolean defaultValueUpdated;

    public HugeElement(final HugeGraph graph) {
        E.checkArgument(graph != null, "HugeElement graph can't be null");
        this.graph = graph;
        this.properties = EMPTY_MAP;
        this.expiredTime = 0L;
        this.removed = false;
        this.fresh = false;
        this.propLoaded = true;
        this.defaultValueUpdated = false;
    }

    public abstract SchemaLabel schemaLabel();

    protected abstract GraphTransaction tx();

    protected abstract <V> HugeProperty<V> newProperty(PropertyKey pk, V val);

    protected abstract <V> void onUpdateProperty(Cardinality cardinality,
                                                 HugeProperty<V> prop);

    protected abstract boolean ensureFilledProperties(boolean throwIfNotExist);

    protected void updateToDefaultValueIfNone() {
        if (this.fresh() || this.defaultValueUpdated) {
            return;
        }
        this.defaultValueUpdated = true;
        // Set default value if needed
        for (Id pkeyId : this.schemaLabel().properties()) {
            if (this.properties.containsKey(intFromId(pkeyId))) {
                continue;
            }
            PropertyKey pkey = this.graph().propertyKey(pkeyId);
            Object value = pkey.defaultValue();
            if (value != null) {
                this.setProperty(this.newProperty(pkey, value));
            }
        }
        this.defaultValueUpdated = true;
    }

    @Override
    public HugeGraph graph() {
        return this.graph;
    }

    protected void removed(boolean removed) {
        this.removed = removed;
    }

    public boolean removed() {
        return this.removed;
    }

    protected void fresh(boolean fresh) {
        this.fresh = fresh;
    }

    public boolean fresh() {
        return this.fresh;
    }

    public boolean isPropLoaded() {
        return this.propLoaded;
    }

    protected void propLoaded() {
        this.propLoaded = true;
    }

    public void propNotLoaded() {
        this.propLoaded = false;
    }

    public void forceLoad() {
        this.ensureFilledProperties(false);
    }

    public void committed() {
        this.fresh = false;
        // Set expired time
        this.setExpiredTimeIfNeeded();
    }

    public void setExpiredTimeIfNeeded() {
        SchemaLabel label = this.schemaLabel();
        if (label.ttl() == 0L) {
            return;
        }
        long now = this.graph.now();
        if (SchemaLabel.NONE_ID.equals(label.ttlStartTime())) {
            this.expiredTime(now + label.ttl());
            return;
        }
        Date date = this.getPropertyValue(label.ttlStartTime());
        if (date == null) {
            this.expiredTime(now + label.ttl());
            return;
        }
        long expired = date.getTime() + label.ttl();
        E.checkArgument(expired > now,
                        "The expired time '%s' of '%s' is prior to now: %s",
                        new Date(expired), this, now);
        this.expiredTime(expired);
    }

    public long expiredTime() {
        return this.expiredTime;
    }

    public void expiredTime(long expiredTime) {
        this.expiredTime = expiredTime;
    }

    public boolean expired() {
        return 0L < this.expiredTime && this.expiredTime < this.graph.now();
    }

    public long ttl() {
        if (this.expiredTime == 0L || this.expiredTime < this.graph.now()) {
            return 0L;
        }
        return this.expiredTime - this.graph.now();
    }

    public boolean hasTtl() {
        return this.schemaLabel().ttl() > 0L;
    }

    public Set<Id> getPropertyKeys() {
        Set<Id> propKeys = InsertionOrderUtil.newSet();
        IntIterator keys = this.properties.keysView().intIterator();
        while (keys.hasNext()) {
            propKeys.add(IdGenerator.of(keys.next()));
        }
        return propKeys;
    }

    public Collection<HugeProperty<?>> getProperties() {
        return this.properties.values();
    }

    public Collection<HugeProperty<?>> getFilledProperties() {
        this.ensureFilledProperties(true);
        return this.getProperties();
    }

    public Map<Id, Object> getPropertiesMap() {
        Map<Id, Object> props = InsertionOrderUtil.newMap();
        for (HugeProperty<?> prop : this.properties.values()) {
            props.put(prop.propertyKey().id(), prop.value());
        }
        // TODO: return MutableIntObjectMap<Object> for this method?
        return props;
    }

    public Collection<HugeProperty<?>> getAggregateProperties() {
        List<HugeProperty<?>> aggrProps = InsertionOrderUtil.newList();
        for (HugeProperty<?> prop : this.properties.values()) {
            if (prop.type().isAggregateProperty()) {
                aggrProps.add(prop);
            }
        }
        return aggrProps;
    }

    @SuppressWarnings("unchecked")
    public <V> HugeProperty<V> getProperty(Id key) {
        return (HugeProperty<V>) this.properties.get(intFromId(key));
    }

    @SuppressWarnings("unchecked")
    public <V> V getPropertyValue(Id key) {
        HugeProperty<?> prop = this.properties.get(intFromId(key));
        if (prop == null) {
            return null;
        }
        return (V) prop.value();
    }

    public boolean hasProperty(Id key) {
        return this.properties.containsKey(intFromId(key));
    }

    public boolean hasProperties() {
        return this.properties.size() > 0;
    }

    public int sizeOfProperties() {
        return this.properties.size();
    }

    public int sizeOfSubProperties() {
        int size = 0;
        for (HugeProperty<?> p : this.properties.values()) {
            size++;
            if (p.propertyKey().cardinality() != Cardinality.SINGLE &&
                p.value() instanceof Collection) {
                size += ((Collection<?>) p.value()).size();
            }
        }
        return size;
    }

    @Watched(prefix = "element")
    public <V> HugeProperty<?> setProperty(HugeProperty<V> prop) {
        if (this.properties == EMPTY_MAP) {
            this.properties = CollectionFactory.newIntObjectMap();
        }
        PropertyKey pkey = prop.propertyKey();

        E.checkArgument(this.properties.containsKey(intFromId(pkey.id())) ||
                        this.properties.size() < MAX_PROPERTIES,
                        "Exceeded the maximum number of properties");
        return this.properties.put(intFromId(pkey.id()), prop);
    }

    public <V> HugeProperty<?> removeProperty(Id key) {
        return this.properties.remove(intFromId(key));
    }

    public <V> HugeProperty<V> addProperty(PropertyKey pkey, V value) {
        return this.addProperty(pkey, value, false);
    }

    @Watched(prefix = "element")
    public <V> HugeProperty<V> addProperty(PropertyKey pkey, V value,
                                           boolean notify) {
        HugeProperty<V> prop = null;
        switch (pkey.cardinality()) {
            case SINGLE:
                prop = this.newProperty(pkey, value);
                if (notify) {
                    /*
                     * NOTE: this method should be called before setProperty()
                     * because tx need to delete index without the new property
                     */
                    this.onUpdateProperty(pkey.cardinality(), prop);
                }
                this.setProperty(prop);
                break;
            case SET:
                prop = this.addProperty(pkey, value, HashSet::new);
                if (notify) {
                    this.onUpdateProperty(pkey.cardinality(), prop);
                }
                break;
            case LIST:
                prop = this.addProperty(pkey, value, ArrayList::new);
                if (notify) {
                    this.onUpdateProperty(pkey.cardinality(), prop);
                }
                break;
            default:
                assert false;
                break;
        }
        return prop;
    }

    @Watched(prefix = "element")
    @SuppressWarnings({"rawtypes", "unchecked"})
    private <V> HugeProperty<V> addProperty(PropertyKey pkey, V value,
                                            Supplier<Collection<V>> supplier) {
        assert pkey.cardinality().multiple();
        HugeProperty<Collection<V>> property;
        if (this.hasProperty(pkey.id())) {
            property = this.getProperty(pkey.id());
        } else {
            property = this.newProperty(pkey, supplier.get());
            this.setProperty(property);
        }

        Collection<V> values;
        if (pkey.cardinality() == Cardinality.SET) {
            if (value instanceof Set) {
                values = (Set<V>) value;
            } else {
                values = CollectionUtil.toSet(value);
            }
        } else {
            assert pkey.cardinality() == Cardinality.LIST;
            if (value instanceof List) {
                values = (List<V>) value;
            } else {
                values = CollectionUtil.toList(value);
            }
        }
        property.value().addAll(pkey.validValueOrThrow(values));

        // Any better ways?
        return (HugeProperty) property;
    }

    public void resetProperties() {
        this.properties = CollectionFactory.newIntObjectMap();
        this.propLoaded = false;
    }

    protected void copyProperties(HugeElement element) {
        if (element.properties == EMPTY_MAP) {
            this.properties = EMPTY_MAP;
        } else {
            this.properties = CollectionFactory.newIntObjectMap(
                    element.properties);
        }
        this.propLoaded = true;
    }

    public HugeElement copyAsFresh() {
        HugeElement elem = this.copy();
        elem.fresh = true;
        return elem;
    }

    public abstract HugeElement copy();

    public abstract Object sysprop(HugeKeys key);

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Element)) {
            return false;
        }

        Element other = (Element) obj;
        if (this.id() == null) {
            return false;
        }

        return this.id().equals(other.id());
    }

    @Override
    public int hashCode() {
        E.checkState(this.id() != null, "Element id can't be null");
        return ElementHelper.hashCode(this);
    }

    @Override
    public int compareTo(HugeElement o) {
        return this.id().compareTo(o.id());
    }

    /**
     * Classify parameter list(pairs) from call request
     *
     * @param keyValues The property key-value pair of the vertex or edge
     * @return Key-value pairs that are classified and processed
     */
    @Watched(prefix = "element")
    public static final ElementKeys classifyKeys(Object... keyValues) {
        ElementKeys elemKeys = new ElementKeys();

        if ((keyValues.length & 1) == 1) {
            throw Element.Exceptions.providedKeyValuesMustBeAMultipleOfTwo();
        }
        for (int i = 0; i < keyValues.length; i = i + 2) {
            Object key = keyValues[i];
            Object val = keyValues[i + 1];

            if (!(key instanceof String) && !(key instanceof T)) {
                throw Element.Exceptions.providedKeyValuesMustHaveALegalKeyOnEvenIndices();
            }
            if (val == null) {
                if (T.label.equals(key)) {
                    throw Element.Exceptions.labelCanNotBeNull();
                }
                // Ignore null value for tinkerpop test compatibility
                continue;
            }

            if (key.equals(T.id)) {
                elemKeys.id = val;
            } else if (key.equals(T.label)) {
                elemKeys.label = val;
            } else {
                elemKeys.keys.add(key.toString());
            }
        }
        return elemKeys;
    }

    public static final Id getIdValue(HugeType type, Object idValue) {
        assert type.isGraph();
        Id id = getIdValue(idValue);
        if (type.isVertex()) {
            return id;
        } else {
            if (id == null || id instanceof EdgeId) {
                return id;
            }
            return EdgeId.parse(id.asString());
        }
    }

    @Watched(prefix = "element")
    protected static Id getIdValue(Object idValue) {
        if (idValue == null) {
            return null;
        }

        if (idValue instanceof String) {
            // String id
            return IdGenerator.of((String) idValue);
        } else if (idValue instanceof Number) {
            // Long id
            return IdGenerator.of(((Number) idValue).longValue());
        } else if (idValue instanceof UUID) {
            // UUID id
            return IdGenerator.of((UUID) idValue);
        } else if (idValue instanceof Id) {
            // Id itself
            return (Id) idValue;
        } else if (idValue instanceof Element) {
            // Element
            return (Id) ((Element) idValue).id();
        }

        // Throw if error type
        throw new UnsupportedOperationException(String.format(
                "Invalid element id: %s(%s)",
                idValue, idValue.getClass().getSimpleName()));
    }

    @Watched(prefix = "element")
    public static final Object getLabelValue(Object... keyValues) {
        Object labelValue = null;
        for (int i = 0; i < keyValues.length; i = i + 2) {
            if (keyValues[i].equals(T.label)) {
                labelValue = keyValues[i + 1];
                E.checkArgument(labelValue instanceof String ||
                                labelValue instanceof VertexLabel,
                                "Expect a string or a VertexLabel object " +
                                "as the vertex label argument, but got: '%s'",
                                labelValue);
                if (labelValue instanceof String) {
                    ElementHelper.validateLabel((String) labelValue);
                }
                break;
            }
        }
        return labelValue;
    }

    public static int intFromId(Id id) {
        E.checkArgument(id instanceof IdGenerator.LongId,
                        "Can't get number from %s(%s)", id, id.getClass());
        return ((IdGenerator.LongId) id).intValue();
    }

    public static final class ElementKeys {

        private Object label = null;
        private Object id = null;
        private Set<String> keys = new HashSet<>();

        public Object label() {
            return this.label;
        }

        public void label(Object label) {
            this.label = label;
        }

        public Object id() {
            return this.id;
        }

        public void id(Object id) {
            this.id = id;
        }

        public Set<String> keys() {
            return this.keys;
        }

        public void keys(Set<String> keys) {
            this.keys = keys;
        }
    }
}
