package org.iri_research.renkan.models;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.iri_research.renkan.Constants;
import org.iri_research.renkan.RenkanException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import com.fasterxml.jackson.annotation.JsonProperty;

@Document(collection="spaces")
public class Space extends AbstractRenkanModel<String> {
	
	@Autowired
	public Space(String id, String title, String description, String binConfig, String uri, String color, String createdBy, String image, Date created) {
		super(id, title, description, uri, color);
		
		this.binConfig = binConfig;
		this.createdBy = createdBy;
		this.setImage(image);
		this.created = created;
		if(this.created == null) {
			this.created = new Date();
		}
	}
	
	public Space() {		
	}

	@Field("bin_config")
	@JsonProperty("bin_config")
	private String binConfig;
	
	@Field("created_by")
	@JsonProperty("created_by")
	private String createdBy = null;	
	private String image;
	private Date created;
	
	public String getImage() {
		return image;
	}

	@JsonProperty("created_by")
	public String getCreatedBy() {
		return createdBy;
	}
	
	public Date getCreated() {
		return created;
	}
	
	public void setCreated(Date date) {
		this.created = date;
		
	}

	@JsonProperty("bin_config")
	public String getBinConfig() {
		return binConfig;
	}

	@JsonProperty("bin_config")
	public void setBinConfig(String bin_config) {
		this.binConfig = bin_config;
	}

	public void setImage(String image) {
		this.image = image;
	}
	
	private String getRawKey(String salt) {		
		StringBuffer key = new StringBuffer(salt!=null?salt+"|":"");
		key.append(this.getId());
		key.append('|');
		key.append(this.getCreated().getTime());
		return key.toString();
	}
		
	public String getKey(String salt) throws RenkanException {
		
		String rawKey = this.getRawKey(salt);
		
		MessageDigest md;
		try {
			md = MessageDigest.getInstance("SHA-256");
		} catch (NoSuchAlgorithmException e) {
			throw new RenkanException("NoSuchAlgorithmException digest: " + e.getMessage(), e);
		}
		String key;
		final SecretKeySpec secret_key = new SecretKeySpec(Constants.KEYHEX.getBytes(), "HmacSHA256");
		md.update(secret_key.getEncoded());
		try {
			key = Hex.encodeHexString(md.digest(rawKey.getBytes("UTF-8")));
		} catch (UnsupportedEncodingException e) {
			throw new RenkanException("UnsupportedEncodingException digest: " + e.getMessage(), e);
		}
		
		return key;
	}
	
	public boolean checkKey(String key, String salt) throws RenkanException {
		

		if(key == null || key.isEmpty()) {
			return false;
		}
				
		String signature = key;
		
		String new_key = this.getKey(salt);
		
		return new_key.equals(signature);
	}
	
}