/*
 * 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.eagle.log.base.taggedlog;

import org.apache.eagle.common.DateTimeUtil;
import org.apache.eagle.log.entity.meta.EntityDefinitionManager;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * rowkey: prefix + timestamp + tagNameValues
 * as of now, all tags will be persisted as a column in hbase table
 * tag name is column qualifier name
 * tag value is column value.
 */
@JsonFilter(TaggedLogAPIEntity.PropertyBeanFilterName)
public class TaggedLogAPIEntity implements PropertyChangeListener, Serializable {
    private static final Logger LOG = LoggerFactory.getLogger(TaggedLogAPIEntity.class);
    private String prefix;
    private long timestamp;
    private Map<String, String> tags;

    public void setExp(Map<String, Object> exp) {
        this.exp = exp;
    }

    public Map<String, Object> getExp() {
        return this.exp;
    }

    /**
     * Extra dynamic attributes.
     * TODO: can we move exp, serializeAlias, serializeVerbose to a wrapper class?
     */
    private Map<String, Object> exp;

    private String encodedRowkey;
    // track what qualifiers are changed
    private Set<String> modifiedProperties = new HashSet<String>();
    protected PropertyChangeSupport pcs
            = new PropertyChangeSupport(this);


    public Map<String, String> getSerializeAlias() {
        return serializeAlias;
    }

    public void setSerializeAlias(Map<String, String> serializeAlias) {
        this.serializeAlias = serializeAlias;
    }

    private Map<String, String> serializeAlias = null;

    public boolean isSerializeVerbose() {
        return serializeVerbose;
    }

    public void setSerializeVerbose(boolean serializeVerbose) {
        this.serializeVerbose = serializeVerbose;
    }

    private boolean serializeVerbose = true;

    public TaggedLogAPIEntity() {
        pcs.addPropertyChangeListener(this);
    }

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }

    public Map<String, String> getTags() {
        return tags;
    }

    public void setTags(Map<String, String> tags) {
        this.tags = tags;
    }

    public String getEncodedRowkey() {
        return encodedRowkey;
    }

    public void setEncodedRowkey(String encodedRowkey) {
        this.encodedRowkey = encodedRowkey;
    }

    protected void valueChanged(String fieldModified) {
        pcs.firePropertyChange(fieldModified, null, null);
    }

    public void propertyChange(PropertyChangeEvent evt) {
        modifiedProperties.add(evt.getPropertyName());
    }

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

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("prefix:");
        sb.append(prefix);
        sb.append(", timestamp:");
        sb.append(timestamp);
        sb.append(", humanReadableDate:");
        sb.append(DateTimeUtil.millisecondsToHumanDateWithMilliseconds(timestamp));
        sb.append(", tags: ");
        if (tags != null) {
            for (Map.Entry<String, String> entry : tags.entrySet()) {
                sb.append(entry.toString());
                sb.append(",");
            }
        }
        sb.append(", encodedRowkey:");
        sb.append(encodedRowkey);
        return sb.toString();
    }

    private static Set<String> getPropertyNames() {
        if (_propertyNames == null) {
            Field[] fields = TaggedLogAPIEntity.class.getDeclaredFields();
            Set<String> fieldName = new HashSet<String>();
            for (Field f : fields) {
                fieldName.add(f.getName());
            }
            _propertyNames = fieldName;
        }
        return _propertyNames;
    }

    private static class BeanPropertyFilter extends SimpleBeanPropertyFilter {
        private static final String prefix = "prefix";
        private static final String encodedRowkey = "encodedRowkey";
        private static final String exp = "exp";
        private static final String timestamp = "timestamp";
        @SuppressWarnings("serial")
        private static final Set<String> verboseFields = new HashSet<String>() {
            {
                add(prefix);
                add(encodedRowkey);
            }
        };

        @Override
        public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception {
            if (pojo instanceof TaggedLogAPIEntity) {
                TaggedLogAPIEntity entity = (TaggedLogAPIEntity) pojo;
                Set<String> modified = entity.modifiedQualifiers();
                Set<String> basePropertyNames = getPropertyNames();
                String writerName = writer.getName();
                if (modified.contains(writerName) || basePropertyNames.contains(writerName)) {
                    if ((!entity.isSerializeVerbose() && verboseFields.contains(writerName))
                            || (timestamp.equals(writerName) && !EntityDefinitionManager.isTimeSeries(entity.getClass()))) {
                        // log skip
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("skip field");
                        }
                    } else {
                        // if serializeAlias is not null and exp is not null
                        if (exp.equals(writerName) && entity.getSerializeAlias() != null && entity.getExp() != null) {
                            Map<String, Object> _exp = new HashMap<String, Object>();
                            for (Map.Entry<String, Object> entry : entity.getExp().entrySet()) {
                                String alias = entity.getSerializeAlias().get(entry.getKey());
                                if (alias != null) {
                                    _exp.put(alias, entry.getValue());
                                } else {
                                    _exp.put(entry.getKey(), entry.getValue());
                                }
                            }
                            entity.setExp(_exp);
                        }
                        // write included field into serialized json output
                        writer.serializeAsField(pojo, jgen, provider);
                    }
                }
            } else {
                writer.serializeAsField(pojo, jgen, provider);
            }
        }
    }

    public static FilterProvider getFilterProvider() {
        if (_filterProvider == null) {
            SimpleFilterProvider _provider = new SimpleFilterProvider();
            _provider.addFilter(PropertyBeanFilterName, new BeanPropertyFilter());
            _filterProvider = _provider;
        }
        return _filterProvider;
    }

    //////////////////////////////////////
    // Static fields
    //////////////////////////////////////
    private static Set<String> _propertyNames = null;
    private static FilterProvider _filterProvider = null;
    static final String PropertyBeanFilterName = "TaggedLogPropertyBeanFilter";

    public static ObjectMapper buildObjectMapper() {
        final JsonFactory factory = new JsonFactory();
        final ObjectMapper mapper = new ObjectMapper(factory);
        mapper.setFilters(TaggedLogAPIEntity.getFilterProvider());
        return mapper;
    }
}