/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* librvngabw
 * Version: MPL 2.0 / LGPLv2.1+
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Major Contributor(s):
 * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.com)
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms
 * of the GNU Lesser General Public License Version 2.1 or later
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
 * applicable instead of those above.
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include <string.h>
#include <stdio.h>

#include "Picture.hxx"

namespace librvngabw
{
librevenge::RVNGString PictureManager::getType(librevenge::RVNGString const &pictData64)
{
	librevenge::RVNGBinaryData data(pictData64);
	unsigned long dataSize=data.size();
	unsigned char const *ptr=data.getDataBuffer();
	if (dataSize<20 || !ptr)
		return "";
	int firstValues[8];
	for (int i=0; i<8; ++i)
		firstValues[i]=int(ptr[2*i]<<8)+int(ptr[2*i+1]);
	switch (firstValues[0])
	{
	case 0:
		if (firstValues[1]==0xc && firstValues[2]==0x6a5c && firstValues[3]==0x2020)
			return "image/jpeg";
		if (firstValues[1]>=0x14 && firstValues[1]<=0x20 && (firstValues[1]&1)==0 &&
		        firstValues[2]==0x6674 && firstValues[3]==0x7970) // or MOV
			return "video/mp4";
		if ((firstValues[1]&0xfff0)==0x1B0)
			return "video/mpg";
		break;
	case 1:
		if (firstValues[1]==0x8 && firstValues[2]==0x1 && firstValues[3]==0x1)
			return "image/img"; // ventura publisher
		break;
	case 0x11:
		if ((firstValues[1]>>8)==0xAF)
			return "image/fli";
		break;
	case 0xff:
		if (firstValues[1]==0xffff && firstValues[2]==0xffff && firstValues[3]==0xffff)
			return "image/mdf";
		break;
	case 0x100:
		if (firstValues[1]==0x900 && firstValues[2]==0x3)
			return "image/wmf";
		if (firstValues[1]==0) // unsure
			return "application/emf";
		break;
	case 0x1da:
		if (firstValues[1]==0x101 && firstValues[2]==0x3)
			return "image/rgb";
		break;
	case 0x2521:
		if (firstValues[1]==0x5053 && firstValues[2]==0x2d41)
			return "application/postscript";
		break;
	case 0x2550:
		if (firstValues[1]==0x4446)
			return "application/pdf";
		break;
	case 0x2562:
		if (firstValues[1]==0x6974) // fuzzy image
			return "image/fbm";
		break;
	case 0x2e52:
		if (firstValues[1]==0x4543) // real player
			return "application/vnd.rn-realmedia";
		if (firstValues[1]==0x4d46) // real media
			return "application/vnd.rn-realmedia";
		break;
	case 0x3026:
		if (firstValues[1]==0xb275 && firstValues[2]==0x8e66) // or asf/wma
			return "video/wmv";
		break;
	case 0x3842:
		if (firstValues[1]==0x5053)
			return "application/octet-stream";
		break;
	case 0x4143:
		if (firstValues[1]==0x3130) // autocad
			return "image/drw";
		break;
	case 0x424d:
		return "image/bmp"; // checkme
	case 0x4350:
		if (firstValues[1]==0x5437 || firstValues[1]==0x5446)
			return "image/cpt";
		break;
	case 0x4357:
		if ((firstValues[1]>>8)==0x53)
			return "image/swf";
		break;
	case 0x4452:
		if (firstValues[1]==0x5747) // macdraw
			return "image/x-macdraw";
		break;
	case 0x464c:
		if (firstValues[1]==0x5601) // flash video
			return "application/x-shockwave-flash";
		break;
	case 0x4749:
		if (firstValues[1]==0x4638)
			return "image/gif";
		break;
	case 0x4920:
		if ((firstValues[1]>>8)==0x49)
			return "image/tiff";
		break;
	case 0x4944:
		if ((firstValues[1]>>8)==0x33)
			return "audio/mpeg";
		break;
	case 0x4949:
		if (firstValues[1]==0x1a00) // canon raw file
			return "image/crw";
		if (firstValues[1]==0x2a00)
			return "image/tiff";
		break;
	case 0x4d4d:
		if (firstValues[1]==0x002a || firstValues[1]==0x002b)
			return "image/tiff";
		return "image/x-macdraw"; // macdraw 1, unsure
	case 0x4a47:
		if (firstValues[1]==0x30e || firstValues[1]==0x40e)
			return "image/art";
		break;
	case 0x4d53:
		if (firstValues[1]==0x5749)
			return "image/wim";
		break;
	case 0x4f67:
		if (firstValues[1]==0x6753)
			return "application/ogg";
		break;
	case 0x5035:
		if ((firstValues[1]>>8)==0x0a)
			return "image/pgm";
		break;
	case 0x5049:
		if (firstValues[1]==0x4354 && firstValues[2]==8) // ADEX
			return "image/img";
		break;
	case 0x5249:
		if (firstValues[1]==0x4646 && firstValues[4]==0x4156 && firstValues[5]==0x4920)
			return "video/avi";
		break;
	case 0x5343:
		if (firstValues[1]==0x4d49) // image software bitmap
			return "image/img";
		break;
	case 0x534D:
		if (firstValues[1]==0x4415 && firstValues[2]==0x5444) // SmartDraw
			return "image/sdr";
		break;
	case 0x5a57:
		if ((firstValues[1]>>8)==0x53)
			return "application/x-shockwave-flash";
		break;
	case 0x646e:
		if (firstValues[1]==0x732e)
			return "audio/x-au";
		break;
	case 0x664c:
		if (firstValues[1]==0x6143 && firstValues[2]==0 && firstValues[3]==0x22)
			return "audio/flac-au";
		break;
	case 0x6674:
		if (firstValues[1]!=0x7970) break;
		if (firstValues[2]==0x3367 || firstValues[2]==0x4d53 || firstValues[2]==0x6973)
			return "video/mp4";
		if (firstValues[2]==0x4d34)
			return "audio/m4a";
		if (firstValues[2]==0x6d70)
			return "video/m4v";
		if (firstValues[2]==0x7174)
			return "video/mov";
		break;
	case 0x6d6f:
		if (firstValues[1]==0x6f76)
			return "video/mov";
		break;
	case 0x7274:
		if (firstValues[1]==0x7370 && firstValues[2]==0x3A2F)
			return "audio/x-realaudio";
		break;
	case 0x762f:
		if (firstValues[1]==0x3101)
			return "image/x-exr";
		break;
	case 0x7e42:
		if (firstValues[1]==0x4b00) // corel paint shop
			return "image/bmp";
		break;
	case 0x8000:
		if (firstValues[1]==0x20 && firstValues[2]==0x312)
			return "audio/x-adx";
		break;
	case 0x8950:
		if (firstValues[1]==0x4e47 && firstValues[2]==0x0d0a)
			return "image/png";
		break;
	case 0x974a:
		if (firstValues[1]==0x4232 && firstValues[2]==0x0d0a)
			return "image/x-jb2";
		break;
	case 0xb168:
		if (firstValues[1]==0xde3a)
			return "image/x-dcx";
		break;
	case 0xc5d0:
		if (firstValues[1]==0xd3c6)
			return "image/postscript";
		break;
	case 0xd7cd:
		if (firstValues[1]==0xc69a)
			return "image/wmf";
		break;
	case 0xff57:
		if (firstValues[1]==0x5043) // word perfect file, assume image
			return "image/x-wpg";
		break;
	case 0xffd8:
		if ((firstValues[1]&0xfff2)==0xffe0)
			return "image/jpeg";
		break;
	default:
		break;
	}
	if ((firstValues[0]>>8)==0x0a && firstValues[1]==0x101)
		return "image/x-pcx";
	if ((firstValues[0]&0xFFF0)==0xffe0)
		return "audio/mpeg";
	if (firstValues[0]==0xFFF1 || firstValues[0]==0xFFF9)
		return "audio/x-aac";
	// test for svg picture
	if (dataSize>100 && firstValues[0]==0x3c3f && firstValues[1]==0x786d && firstValues[2]==0x6c20)   // <?xml
	{
		int pos=6;
		do
		{
			if (ptr[pos]!=0xa)
				continue;
			if ((unsigned long)(pos+13)>dataSize || ptr[++pos]!='<') break;
			if (ptr[++pos]=='!') // skip < and read new char
			{
				if (strncmp("!DOCTYPE ", reinterpret_cast<char const *>(ptr+pos), 9)!=0)
					break;
				pos+=9;
			}
			if ((unsigned long)(pos+4)>dataSize) break;
			if (strncmp("svg ", reinterpret_cast<char const *>(ptr+pos), 4)!=0 &&
			        strncmp("SVG ", reinterpret_cast<char const *>(ptr+pos), 4)!=0)
				break;
			return "image/svg+xml";
		}
		while (++pos<100);
	}
	// test for mac picture
	for (int st=0; st<2; ++st)
	{
		if (firstValues[1]<firstValues[3] && firstValues[2]<firstValues[4] && // dim
		        (firstValues[5]==0x1101 || (firstValues[5]==0x0011 && firstValues[6]==0x2ff && firstValues[7]==0xc00)))
			return "image/x-pict";
		if (st==1 || dataSize<512+20)
			break;
		for (int i=0; i<8; ++i)
			firstValues[i]=int(ptr[512+2*i]<<8)+int(ptr[512+2*i+1]);
	}
	return "";
}
}
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
