package com.ekexiu.portal.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;

import org.jfw.apt.web.annotation.Path;
import org.jfw.apt.web.annotation.operate.Get;
import org.jfw.apt.web.annotation.operate.Post;
import org.jfw.util.JpgUtil;
import org.jfw.util.StringUtil;
import org.jfw.util.context.JfwAppContext;
import org.jfw.util.exception.JfwBaseException;
import org.jfw.util.io.IoUtil;

@Path("/image")
public class ImageService {
	private File tmpPath;
	private File imagePath;
	private File headPath;
	private File orgPath;
	private File resourcePath;
	private int largeHeadPhotoWidth = 200;
	private int largeHeadPhotoHeight = 200;
	private int middleHeadPhotoWidth = 200;
	private int middleHeadPhotoHeight = 200;
	private int smallHeadPhotoWidth = 200;
	private int smallHeadPhotoHeight = 200;

	private File defaultHeadPhoto;
	private File defaultOrgLogo;
	private File defaultResourcePhoto;

	private byte[] dli;
	private byte[] dmi;
	private byte[] dsi;
	private byte[] dol;
	private byte[] dsl;

	public File getDefaultHeadPhoto() {
		return defaultHeadPhoto;
	}

	public void setDefaultHeadPhoto(File defaultHeadPhoto) {
		this.defaultHeadPhoto = defaultHeadPhoto;
	}

	public File getDefaultOrgLogo() {
		return defaultOrgLogo;
	}

	public void setDefaultOrgLogo(File defaultOrgLogo) {
		this.defaultOrgLogo = defaultOrgLogo;
	}

	public File getTmpPath() {
		return tmpPath;
	}

	public void setTmpPath(File tmpPath) {
		this.tmpPath = tmpPath;
	}

	public File getImagePath() {
		return imagePath;
	}

	public void setImagePath(File imagePath) {
		this.imagePath = imagePath;
		this.headPath = new File(this.imagePath, "head");
		this.orgPath = new File(this.imagePath, "org");
		this.resourcePath = new File(this.resourcePath, "resource");
	}

	public int getLargeHeadPhotoWidth() {
		return largeHeadPhotoWidth;
	}

	public void setLargeHeadPhotoWidth(int largeHeadPhotoWidth) {
		this.largeHeadPhotoWidth = largeHeadPhotoWidth;
	}

	public int getLargeHeadPhotoHeight() {
		return largeHeadPhotoHeight;
	}

	public void setLargeHeadPhotoHeight(int largeHeadPhotoHeight) {
		this.largeHeadPhotoHeight = largeHeadPhotoHeight;
	}

	public int getMiddleHeadPhotoWidth() {
		return middleHeadPhotoWidth;
	}

	public void setMiddleHeadPhotoWidth(int middleHeadPhotoWidth) {
		this.middleHeadPhotoWidth = middleHeadPhotoWidth;
	}

	public int getMiddleHeadPhotoHeight() {
		return middleHeadPhotoHeight;
	}

	public void setMiddleHeadPhotoHeight(int middleHeadPhotoHeight) {
		this.middleHeadPhotoHeight = middleHeadPhotoHeight;
	}

	public int getSmallHeadPhotoWidth() {
		return smallHeadPhotoWidth;
	}

	public void setSmallHeadPhotoWidth(int smallHeadPhotoWidth) {
		this.smallHeadPhotoWidth = smallHeadPhotoWidth;
	}

	public int getSmallHeadPhotoHeight() {
		return smallHeadPhotoHeight;
	}

	public void setSmallHeadPhotoHeight(int smallHeadPhotoHeight) {
		this.smallHeadPhotoHeight = smallHeadPhotoHeight;
	}

	public File getTmpDir() {
		return tmpPath;
	}

	public void setTmpDir(File tmpPath) {
		this.tmpPath = tmpPath;
	}
	
	public File getDefaultResourcePhoto() {
		return defaultResourcePhoto;
	}

	public void setDefaultResourcePhoto(File defaultResourcePhoto) {
		this.defaultResourcePhoto = defaultResourcePhoto;
	}
	
	/**
	 * 判断是否有专家头像
	 * @param id 专家ID
	 * @return 有头像返回1，没有返回0.
	 */
	public int hasProfessorImage(String id) {
		String headPath = this.headPath+"/"+id+"_l.jpg";
		File file = new File(headPath);
		if(file.exists()){
			return 1;
		}else{
			return 0;
		}
	}

	private File getTemplateFielName(File path, String suffix) {
		File result = null;
		while (result == null) {
			String fn = StringUtil.buildUUID() + ".jpg";
			result = new File(path, fn);
			if (result.exists())
				result = null;
		}
		return result;
	}

	private void saveJpg(File file, byte[] data, int w, int h) throws IOException {
		ByteArrayInputStream in = new ByteArrayInputStream(data);
		FileOutputStream out = new FileOutputStream(file);
		try {
			JpgUtil.zoom(in, out, w, h);
		} finally {
			out.flush();
			out.close();
		}
	}

	private byte[] zoomImage(byte[] src, int w, int h) throws IOException {
		ByteArrayInputStream in = new ByteArrayInputStream(src);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		JpgUtil.zoom(in, out, w, h);
		out.flush();
		return out.toByteArray();
	}

	private byte[] readTmpFile(String fn) throws JfwBaseException {
		File file = new File(this.tmpPath, fn);
		if (!file.exists())
			throw new JfwBaseException(90, "head photo not exists");
		try {
			InputStream in = new FileInputStream(file);
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			IoUtil.copy(in, out, true, true);
			return out.toByteArray();
		} catch (IOException e) {
			throw new JfwBaseException(91, "read temp head photo error", e);
		}
	}

	@Path("/headPhoto/preview")
	@Get
	public String[] preview(int left, int right, int top, int bottom, String fn) throws JfwBaseException {

		byte[] fileData = this.readTmpFile(fn);

		try {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			JpgUtil.cutByPerCent(new ByteArrayInputStream(fileData), out, top, bottom, left, right);
			fileData = out.toByteArray();
		} catch (IOException e) {
			throw new JfwBaseException(0, "cart image error", e);
		}
		File small = this.getTemplateFielName(this.tmpPath, ".jpg");
		File middle = this.getTemplateFielName(this.tmpPath, ".jpg");
		File large = this.getTemplateFielName(this.tmpPath, ".jpg");
		try {
			this.saveJpg(small, fileData, this.smallHeadPhotoWidth, this.smallHeadPhotoHeight);
			this.saveJpg(middle, fileData, this.middleHeadPhotoWidth, this.middleHeadPhotoHeight);
			this.saveJpg(large, fileData, this.largeHeadPhotoWidth, this.largeHeadPhotoHeight);
		} catch (IOException e) {
			small.delete();
			middle.delete();
			large.delete();
			throw new JfwBaseException(92, "save tmp file error", e);
		}
		final String[] files = new String[] { small.getAbsolutePath(), middle.getAbsolutePath(), large.getAbsolutePath() };
		JfwAppContext.getScheduledExecutorService().schedule(new Runnable() {
			@Override
			public void run() {
				for (String file : files) {
					new File(file).delete();
				}
			}
		}, 30, TimeUnit.MINUTES);

		return new String[] { small.getName(), middle.getName(), large.getName() };
	}

	private void initDefaultImage() {
		if (this.dli != null)
			return;
		synchronized (this) {
			if (this.dli != null)
				return;

			try {
				byte[] dd = IoUtil.readStream(new FileInputStream(this.defaultHeadPhoto), true);
				this.dli = this.zoomImage(dd, this.largeHeadPhotoWidth, this.largeHeadPhotoHeight);
				this.dmi = this.zoomImage(dd, this.middleHeadPhotoWidth, this.middleHeadPhotoHeight);
				this.dsi = this.zoomImage(dd, this.smallHeadPhotoWidth, this.smallHeadPhotoHeight);
				this.dol = IoUtil.readStream(new FileInputStream(this.defaultOrgLogo), true);
				this.dsl = IoUtil.readStream(new FileInputStream(this.defaultResourcePhoto), true);
			} catch (IOException e) {
				this.dli = null;
				this.dmi = null;
				this.dsi = null;
				this.dol = null;
				this.dsl = null;
				throw new RuntimeException("init image error", e);
			}
		}
	}

	public void saveDefaultHeadImage(String id) throws IOException {
		this.initDefaultImage();
		IoUtil.saveStream(new FileOutputStream(new File(this.headPath, id + "_s.jpg")), dsi, true);
		IoUtil.saveStream(new FileOutputStream(new File(this.headPath, id + "_m.jpg")), dmi, true);
		IoUtil.saveStream(new FileOutputStream(new File(this.headPath, id + "_l.jpg")), dli, true);
	}

	public void saveDefaultOrgLogo(String id) throws IOException {
		this.initDefaultImage();
		IoUtil.saveStream(new FileOutputStream(new File(this.orgPath, id + ".jpg")), this.dol, true);
	}
	
	public void saveDefaultResourcePhoto(String resourceId) throws IOException {
		this.initDefaultImage();
		IoUtil.saveStream(new FileOutputStream(new File(this.resourcePath, resourceId + ".jpg")), this.dsl, true);
	}

	@Post
	@Path("/org")
	public void saveOrgLogo(String id, String fn) throws IOException {
		InputStream in = new FileInputStream(new File(this.tmpPath, fn));
		try {
			IoUtil.copy(in, new FileOutputStream(new File(this.orgPath, id + ".jpg")), false, true);
		} finally {
			in.close();
		}
	}
	
	@Post
	@Path("/head")
	public void saveHeadPhoto(String id, String fn,int x,int y,int w,int h) throws JfwBaseException, SQLException, IOException {
		byte[] src = this.readTmpFile(fn);
		src = JpgUtil.read(src);
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		JpgUtil.cutByPerCent(new ByteArrayInputStream(src), os, x, y, w, h);
		src = os.toByteArray();
		byte[] li = this.zoomImage(src, this.largeHeadPhotoWidth, this.largeHeadPhotoHeight);
		byte[] mi = this.zoomImage(src, this.middleHeadPhotoWidth, this.middleHeadPhotoHeight);
		byte[] si = this.zoomImage(src, this.smallHeadPhotoWidth, this.smallHeadPhotoHeight);
		IoUtil.saveStream(new FileOutputStream(new File(this.headPath, id + "_s.jpg")), si, true);
		IoUtil.saveStream(new FileOutputStream(new File(this.headPath, id + "_m.jpg")), mi, true);
		IoUtil.saveStream(new FileOutputStream(new File(this.headPath, id + "_l.jpg")), li, true);
	}

}
