//SCRIPT INFO:

(*	Following until 'SCRIPT BEGINS HERE...' is documentation.
	Please see 'USER OPTIONS' in the body of the script.

---------------------------------------------

SCRIPT:		AllRovi
CO-AUTHORS:	Ivek23 and rick.ca
VERSION:		0.1.1.6
DATE:		12/28/2012

---------------------------------------------

CHANGE LOG:

v 0.1.1.0		rick.ca: initial "public" release to auto-update system
			only change is in version number (was 0.1.0.17)
			previous versions posted at forum topic:
			http://www.videodb.info/forum_en/index.php/topic,2487.msg12988.html
v 0.1.1.1		Ivek23: move mfDecription to bottom of ParseMovie procedure per forum post:
			http://www.videodb.info/forum_en/index.php/topic,2496.msg13284.html#msg13284
v 0.1.1.2		Ivek23: improvement to ParseSearchResults section for multiple hits per forum post:
			http://www.videodb.info/forum_en/index.php/topic,2496.msg13301.html#msg13301
			rick.ca: change all Options to 'True' since they are controlled by Overwrite settings anyway.
v 0.1.1.3		rick.ca: fix inconsistent ~Characteristics~ by resetting curPos to topPos per forum post:
			http://www.videodb.info/forum_en/index.php/topic,2496.msg13345.html#msg13345
			Ivek23: fix ParseCast with only crew in the Cast & Crew tab per forum post:
			http://www.videodb.info/forum_en/index.php/topic,2496.msg13348.html#msg13348
v 0.1.1.4		Ivek23: improvement to ParsePage function (ParseSearchResults section) per forum post:
			http://www.videodb.info/forum_en/index.php/topic,2496.msg16185.html#msg16185
v 0.1.1.5		Ivek23: improvement to ~Moods~ from 'Characteristics' section per forum post:
			http://www.videodb.info/forum_en/index.php/topic,2496.msg16192.html#msg16192
v 0.1.1.6		Ivek23: improvement to ParsePage function (ParseSearchResults section) per forum post:
			http://www.videodb.info/forum_en/index.php/topic,,2496.msg16250.html#msg16250

---------------------------------------------

FIELD USE:

Field names in comments are enclosed in "~" so they are easier to find in the script.
Use with your editor's search function to find applicable code sections.

Rovi data:			PVD field:		FN:		Type/Comments:
---------				---------			--		-------------
Actors				~ctActors~		1, 3		credits (if GET_ACTORS true)
AMG ID				~AMG ID~					short text
Awards				~Awards~					memo (link to Rovi Awards tab)
Cast					~Cast~					memo
Crew					~Crew~					memo
Category				~Category.Rovi~			multiselect list
											—not to be confused with ~mfCategory~ (used for 'Themes')
Characteristics		~Characteristics~			memo ('Attributes' and 'Moods' removed)
				AND	~Attributes~				multiselect list (pulled from 'Characteristics')
				AND	~Moods~					multiselect list (pulled from 'Characteristics')
				AND	~Mood links~				memo (hyperlinks to AllMovie mood pages
											—if available in web archive
Country				~mfCountry~		1		standard multiselect list
				OR	~Country~			2		multiselect list
Cover-art				~Poster~			1, 3		standard (if GET_POSTER true)
Directed by			~ctDirectors~		1		standard multiselect list
Flags				~Flags~					multiselect list
Genres				~mfGenre~			1		standard multiselect list
				OR	~Genres~			2		multiselect list
				AND	~Genre links~				memo (links to Rovi Genre page)
MPAA rating			~MPAA rating~				short text
Produced by			~mfStudio~		1		standard short text
				OR	~Produced by~		2		multiselect list
Review				~Review~					memo
Release date			~Released~				short text (multiple dates)
OR	Released			~Released~				short text (more common single date)
Releases				~mfFeatures~		1		standard memo (link to Rovi Releases tab)
				OR	~Releases~		2		memo (link to each Rovi DVD page)
Released by 			~Released by~ 				short text
Rovi rating			~mfRating~		1, 3		'Additional rating' named 'Rovi' (if GET_RATING true)
				OR	~Rovi rating~		2		rating
Run time				~mfDuration~		1, 3		standard number (if GET_DURATION true)
				OR	~Run time~		2		number (minutes)
Synopsis				~mfDescription~			standard memo
											—use PVD preference to save in ANY available memo field
Sub-Genres			~Sub-Genres~				multiselect list
				OR	~Sub-Genre links~			memo (links to Rovi page)
Title				~mfTitle~			1		standard short text
				OR	~Title~			2		short text
Year					~mfYear~			1		standard number (from Rovi 'Title (Year)' heading)
				OR	~Year~			2		short string
Themes				~mfCategory~		1		standard multiselect list (if GET_THEMES true)
				OR	~Themes~			2		multiselect list
Updated				~Updated~					long text
URL					~mfURL~			1		standard memo
				OR	~URL~			2		memo

AllMovie data no longer available:

Color type		Color type
From book			Book
Keywords			Keywords
Set in			Set in
Tones			mfTags

Footnotes:

1. Control the use of standard fields using the "Overwrite Fields" plugin preferences in the main program.

2. Where data is saved to a standard field, the script also saves the data to custom field. This allows a number of options:

	i) Use the data saved to the standard field (normally the default) and ignore the custom field. Data saved to a non-existent custom field goes nowhere.

	ii) Ignore the data entirely by disabling the standard field in the "Overwrite fields" options.

	iii) Add the custom field to PVD and disable the standard field so it's free for use by another plugin or script.

Some of these optional custom fields are named the same as their standard counterparts. To avoid confusion, you may wish to rename them (i.e., in the script, in PVD and your skin). For example, change "Year" to "Rovi Year"—so as to not be confused with the standard field used by another source.

3. 'User Options' are set in the body of the script below. Recommended: Leave them all set to 'True' and use Preferences > Plugins > AllRovi > Overwrite fields to control how these items are to be updated.


TYPES AND FUNCTIONS
Additional types and functions that can be used in scripts:

Types
	TWIDEARRAY : array of String

Field functions
	procedure AddSearchResult(Title1, Title2, Year, URL, PreviewURL : String)
	procedure AddFieldValue(AField: Integer; AValue : String)
	procedure AddMoviePerson(Name, TransName, Role, URL : String; AType : Byte)
	procedure AddPersonMovie(Title, OrigTitle, Role, Year, URL : String; AType : Byte)
	procedure AddAward(Event, Award, Category, Recipient, Year: String; const Won : Boolean)
	procedure AddAwardEx(Event, Award, Category, RecipientVal1, RecipientVal2, Year : String; const Won : Boolean);
	procedure AddConnection(Title, OrigTitle, Category, URL, Year: String)
	procedure AddEpisode(Title, OrigTitle, Description, URL, Year, Season, Episode : String)

String functions
	function Pos(Substr : String; Str: String): Integer
	function PosFrom(const SubStr, Str : String; FromIndex : Integer) : Integer
	function LastPos(const SubStr, Str : String) : Integer
	function PrevPos(const SubStr, Str : String; APos : Integer) : Integer
	function RemoveTags(AText : String; doLineBreaks : Boolean) : String
	function ExplodeString(AText : String; var Items : TWideArray; Delimiters : String) : Integer
	function Copy(S: String; Index, Count: Integer): String
	procedure Delete(var S: String; Index, Count: Integer)
	procedure Insert(Source: String; var Dest: String; Index: Integer)
	function Length(S: String): Integer
	function Trim(S: String): String
	function CompareText(S1, S2: String): Integer
	function CompareStr(S1, S2: String): Integer
	function UpperCase(S: String): String
	function LowerCase(S: String): String
	function AnsiString(S, OldPattern, NewPattern: String; All : Boolean; IgnoreCase : Boolean; WholeWord: Boolean): String
	function StrToInt(const S: String): Integer
	function IntToStr(const Value: Integer): String
	function StrToFloat(const S: String): Extended
	function FloatToStr(const Value: Extended): String
	function CurrentDateTime : Extended
	function DateToStr(Value : Extended) : String
	function TimeToStr(Value : Extended) : String
	function HTMLValues(const HTML : String; ABegin, AEnd, ItemBegin, ItemEnd : String; ValDelim : String; var Pos : Integer) : String
	function HTMLValues2(const HTML : String; ABegin, AEnd, ItemBegin, ItemEnd : String; ValDelim : String; var Pos : Integer) : String
	function TextBetween(const HTML : String; ABegin, AEnd : String; doLineBreaks : Boolean; var Pos : Integer) : String
	function HTMLToText(const HTML : String) : String

  procedure ShowMessage(const Msg, Head : String)
*)

//SCRIPT BEGINS HERE...

//Some useful constants

const

//Script types
	stMovies		= 0;
	stPeople		= 1;
	stPoster		= 2;
	
//Script modes
	smSearch		= 0;
	smNormal		= 1;
	smCast		= 2;
	smReview		= 3;
	smCredits		= 4;
	smDVDReleases	= 5;
	smPoster		= 6;
	smFinished	= 7;
	
//Parse results
	prError		= 0;
	prFinished	= 1;
	prList		= 2;
	prListImage	= 3;
	prDownload	= 4;
	
//Prefix modes
	pmNone		= 0;
	pmEnd		= 1;
	pmBegin		= 2;
	pmRemove		= 3;
	
//Download methods
	dmGET		= 0;
	dmPOST		= 1;
	
//Movie fields
	mfURL		= 0;
	mfTitle		= 1;
	mfOrigTitle	= 2;
	mfAka		= 3;
	mfYear		= 4;
	mfGenre		= 5;
	mfCategory	= 6;
	mfCountry		= 7;
	mfStudio		= 8;
	mfMPAA		= 9;
	mfRating		= 10;	//This is 'Additional rating', not 'Rating'
	mfTags		= 11;
	mfTagline		= 12;
	mfDescription	= 13;
	mfDuration	= 14;
	mfFeatures	= 15;
	
//People fields
	pfURL		= 0;
	pfName		= 1;
	pfTransName	= 2;
	pfAltNames	= 3;
	pfBirthday	= 4;
	pfBirthplace	= 5;
	pfGenre		= 6;
	pfBio		= 7;
	pfDeathDate	= 8;
	
//Credits types
	ctActors		= 0;
	ctDirectors	= 1;
	ctWriters		= 2;
	ctComposers	= 3;
	ctProducers	= 4;
	
//Script data
	SCRIPT_VERSION	= '0.1.1.6';
	SCRIPT_NAME	= 'AllRovi';
	SCRIPT_DESC	= '[EN] Get Movie Information from AllRovi';
	SCRIPT_LANG	= $09; //English
	SCRIPT_TYPE	= stMovies;
	
	BASE_URL		= 'http://www.allrovi.com';
	RATING_NAME	= 'Rovi';
	SEARCH_STR	= 'http://www.allrovi.com/search/movies/%s';
	CODE_PAGE		= 65001;	//Use 0 for Autodetect
	
//User Options
	GET_ACTORS	= True;	//Set to False to ensure ~ctActors~ not added even if 'Overwrite fields' setting allows
	GET_DURATION	= True;	//Set to False to ensure ~mfDuration~ not set even if 'Overwrite fields' setting allows
						//Note the program will overwrite this with the actual media duration in any case
	GET_POSTER	= True;	//Set to False if posters not wanted (or to handle bad image URL causing HTTP 404 error)
	GET_RATING	= True;	//Set to False to ensure ~mfRating~ not set even if 'Overwrite setting' fields setting allows
	GET_THEMES	= True;	//Set to False to ensure ~mfCategory~ not added even if 'Overwrite fields' setting allows


//Global variables
var
ELI : Integer;
Mode : Byte;
ExtraLinks : array [smCast..smPoster] of String;

//Functions
function GetScriptVersion : String;
begin
	Result := SCRIPT_VERSION;
end;

function GetScriptName : String;
begin
	Result :=  SCRIPT_NAME;
end;

function GetScriptDesc : String;
begin
	Result := SCRIPT_DESC;
end;

function GetRatingName : String;
begin
	Result := RATING_NAME;
end;

function GetScriptLang: Cardinal;
begin
	Result := SCRIPT_LANG;
end;

function GetCodePage : Cardinal;
begin
	Result := CODE_PAGE;
end;

function GetBaseURL : AnsiString;
begin
	Result := BASE_URL;
end;

function GetDownloadURL : AnsiString;
begin
	if (Mode = smSearch) then
		Result := SEARCH_STR
	else
		Result := ExtraLinks[Mode];
end;

function GetDownloadMethod : Byte;
begin
	Result := dmGET;
end;

function GetPrefixMode : Byte;
begin
	Result := pmBegin;
end;

function GetScriptType : Byte;
begin
	Result := SCRIPT_TYPE;
end;

function GetCurrentMode : Byte;
begin
	Result := Mode;
end;


function RemoveTagsEx(AText : String) : String;
var
	B, E : Integer;
begin
	Result	:= AText;
	B		:= PosFrom('<', Result, 1);
	E		:= PosFrom('>', Result, B);

	while (B > 0) AND (B < E) do begin
		Delete(Result, B, E - B + 1);
		B	:= Pos('<', Result);
		E	:= Pos('>', Result);
	end;
end;

procedure ParseReview(HTML : String);
var
	curPos, endPos : Integer;
	TmpStr, TmpStr1, TmpStr2, TmpStr3, TmpStr4, TmpStr5 : String;
begin
	curPos := Pos('<div class="tab-title">', HTML);
	if curPos < 1 then
		Exit;

//~Review~

curPos := PosFrom('<span>', HTML, curPos);
endPos := PosFrom('</span>', HTML, curPos);
TmpStr5 := TextBetween(HTML, '<span>', '</span>', True, curPos);
curPos := PosFrom('<span>by', HTML, curPos);
endPos := PosFrom('</span>', HTML, curPos);

TmpStr3 := TextBetween(HTML, '<span>by ', '</span>', True, curPos)

curPos := PosFrom('<strong>', HTML, curPos);
endPos := PosFrom('</strong>', HTML, curPos);
TmpStr4 := TextBetween(HTML, '<strong>', '</strong>', True, curPos);

curPos := PosFrom('<p>', HTML, curPos);
endPos := PosFrom('</p>', HTML, curPos);
TmpStr := Copy(HTML, curPos, endPos - curPos);
TmpStr1 := StringReplace(TmpStr, ' -- ', '—', True, True, False);
TmpStr2 := StringReplace(TmpStr1, ' --- ', '—', True, True, False);
TmpStr := StringReplace(TmpStr2, '--', '—', True, True, False);
TmpStr1 := StringReplace(TmpStr, #13#13#13#13, #13#10#13#10, True, True, False);
TmpStr2 := RemoveTagsEx(TmpStr1);

AddCustomFieldValueByName('Review', TmpStr2 + #13 + '—' + TmpStr3);

end;


//~Cast~ or ~ctActors~
//save entire Cast tab to custom memo field, as well as individual actors.

procedure ParseCast(HTML : String);
var
	curPos, endPos : Integer;
	TmpStr : String;
	Name, Role, URL : String;
begin
curPos := Pos('<div class="tabset-content main-tab-pane">', HTML);
if curPos < 1 then

curPos := Pos('<div class="description-box">', HTML);
if curPos < 1 then
	Exit;
 
TmpStr := '';

endPos := curPos;
curPos := PosFrom('http://www.allrovi.com/name/', HTML, curPos);

while (curPos > 0) AND (curPos < PosFrom('</table>', HTML, endPos)) do begin
	endPos	:= PosFrom('">', HTML, curPos);
	URL		:= Copy(HTML, curPos, endPos - curPos);

	curPos	:= endPos + 2;
	endPos	:= PosFrom('</a>', HTML, curPos);
	Name		:= Copy(HTML, curPos, endPos - curPos);

	curPos	:= PosFrom('>', HTML, endPos);
	if curPos > 0 then begin
		curPos	:= curPos + 2;
		endPos	:= PosFrom('</td', HTML, curPos);
		Role		:= Copy(Trim(Copy(HTML, curPos + 4, endPos - curPos - 4)), 5, endPos - curPos - 4);
end else begin
	Role		:= '';
	curPos	:= endPos;
end;

if GET_ACTORS then
	AddMoviePerson(Name, '', '', URL, ctActors);

if TmpStr <> '' then
	TmpStr := TmpStr + #13;
if URL <> '' then
	TmpStr := TmpStr + '<link url="' + URL + '">';
TmpStr := TmpStr + Name;
if Role <> '' then
	TmpStr := TmpStr + ' • ' + Role;
if URL <> '' then
	TmpStr := TmpStr + '</link>';
if curPos > 0 then
	curPos := PosFrom('http://www.allrovi.com/name/', HTML, curPos)
else
	Exit;
end;

AddCustomFieldValueByName('Cast', TmpStr);


//~Crew~

if curPos < 1 then
	Exit;

TmpStr := '';

endPos := curPos;
curPos := PosFrom('http://www.allrovi.com/name/', HTML, curPos);
while (curPos > 0) AND (curPos < PosFrom('</dl>', HTML, endPos)) do begin
	endPos	:= PosFrom('">', HTML, curPos);
	URL		:= Copy(HTML, curPos, endPos - curPos);

	curPos	:= endPos + 2;
	endPos	:= PosFrom('</a>', HTML, curPos);
	Name		:= Copy(HTML, curPos, endPos - curPos);

	curPos	:= PosFrom('>', HTML, endPos);
	if curPos > 0 then begin
		curPos	:= curPos + 2;
		endPos	:= PosFrom('</dd>', HTML, curPos);
		Role		:= Copy(Trim(Copy(HTML, curPos + 4, endPos - curPos - 4)), 5, endPos - curPos - 4);

	end else begin
		Role		:= '';
		curPos	:= endPos;
	end;

if TmpStr <> '' then
	TmpStr := TmpStr + #13;
if URL <> '' then
	TmpStr := TmpStr + '<link url="' + URL + '">';
TmpStr := TmpStr + Name;

if Role <> '' then
	TmpStr := TmpStr + ' • ' + Role;
if URL <> '' then
	TmpStr := TmpStr + '</link>';

if curPos > 0 then
	curPos := PosFrom('http://www.allrovi.com/name/', HTML, curPos)
else
	Exit;

end;

AddCustomFieldValueByName('Crew', TmpStr);

end;


//~Releases~

procedure ParseDVDReleases(HTML : String);
var
	curPos, endPos : Integer;
	TmpStr : String;
	Name, Role, Years, Disc, URL : String;
begin
curPos := Pos('<div class="tabset-content main-tab-pane">', HTML);
if curPos < 1 then
	Exit;

TmpStr := '';
endPos := curPos;
endPos := PosFrom('<td class="first">', HTML, curPos);
curPos := PosFrom('<span>', HTML, endPos) + 6;
endPos := PosFrom('</span>', HTML, curPos);
  Disc := Trim(Copy(HTML, curPos, endPos - curPos));
endPos := curPos;
curPos := PosFrom('http://www.allrovi.com/movies/movie/', HTML, curPos);

while (curPos > 0) AND (curPos < PosFrom('</table>', HTML, endPos)) do begin
	endPos	:= PosFrom('">', HTML, curPos);
	URL		:= Copy(HTML, curPos, endPos - curPos);

	curPos	:= endPos + 2;
	endPos	:= PosFrom('</a>', HTML, curPos);
	Name		:= Copy(HTML, curPos, endPos - curPos);

	curPos := PosFrom('>', HTML, endPos);
	if curPos > 0 then begin
		curPos	:= curPos + 2;
		endPos	:= PosFrom('</div>', HTML, curPos);
		Role		:= Copy(Trim(Copy(HTML, curPos + 13, endPos - curPos - 13)), 20, endPos - curPos - 19);
end else begin
	Role		:= '';
	curPos	:= endPos;
end;

endPos	:= curPos;
endPos	:= PosFrom('<td>', HTML, curPos);
curPos	:= PosFrom('<td>', HTML, endPos) + 4;
endPos	:= PosFrom('</td>', HTML, curPos);
Years	:= Trim(Copy(HTML, curPos, endPos - curPos));

if TmpStr <> '' then
	TmpStr := TmpStr + #13;
if URL <> '' then
	TmpStr := TmpStr + '<link url="' + URL + '">';
TmpStr := TmpStr + Name + '</link>';

if Role <> '' then
	TmpStr := TmpStr + '  •  ' + Role;

if Years  <> '' then
	TmpStr := TmpStr + '  •  ' +  Years;

if curPos > 0 then
	curPos := PosFrom('http://www.allrovi.com/movies/movie/', HTML, curPos)
else
	Exit;
end;

AddCustomFieldValueByName('Releases', TmpStr);

end;


procedure ParseMovie(MovieURL : String; HTML : String);
var
	curPos, endPos, topPos, L, H, R : Integer;
	Name, URL, TmpStr, TmpStr1, TmpStr2, TmpStr3, TmpStr4, TmpStr5 : String;
begin

//Date ~Updated~ (choose simple or verbose version)

//AddCustomFieldValueByName('Updated', DateToStr(CurrentDateTime));																	// Simple
//AddCustomFieldValueByName('Updated', DateToStr(CurrentDateTime) + ' at ' + TimeToStr(CurrentDateTime));									// Verbose
AddCustomFieldValueByName('Updated', DateToStr(CurrentDateTime) + ' at ' + TimeToStr(CurrentDateTime) + ' • ' + SCRIPT_NAME + ' ' + SCRIPT_VERSION);	// Annoying


//Get ~mfURL~ or ~URL~

endPos := Pos('" class="title">', HTML);
if endPos > 0 then begin
	curPos := PrevPos('<div class="details"><a href="', HTML, endPos);
	AddFieldValue(mfURL, Copy(HTML, curPos + 21, endPos - curPos - 21));
end else
AddFieldValue(mfURL, MovieURL);
AddCustomFieldValueByName('URL', '<link url="' + MovieURL + '">' + MovieURL + '</link>');

//Get Review URL
endPos := Pos('"><span>review</span>', HTML);
if endPos > 0 then begin
	curPos := PrevPos('href="/movies', HTML, endPos);
	ExtraLinks[smReview] := BASE_URL + Copy(HTML, curPos + 6, endPos - curPos - 6);
end;

//Get Cast URL
endPos := Pos('"><span>cast & crew</span></a>', HTML);
if endPos > 0 then begin
	curPos := PrevPos('href="/movies', HTML, endPos);
	ExtraLinks[smCast] := BASE_URL + Copy(HTML, curPos + 6, endPos - curPos - 6);
end;

//Get Awards URL
endPos := Pos('"><span>awards</span>', HTML);
if endPos > 0 then begin
	curPos := PrevPos('href="/movies', HTML, endPos);
	TmpStr := BASE_URL + Copy(HTML, curPos + 6, endPos - curPos - 6);
end;


//~Awards~

if TmpStr <> '' then
  	AddCustomFieldValueByName('Rovi Awards', '<link url="' + TmpStr + '">Rovi Awards page</link>');

//Get ~Releases~ URL and optionally save in ~mfFeatures~
 
endPos := Pos('"><span>releases</span>', HTML);
if endPos > 0 then begin
	curPos := PrevPos('href="/movies', HTML, endPos);
	ExtraLinks[smDVDReleases] := BASE_URL + Copy(HTML, curPos + 6, endPos - curPos - 6);
end;

endPos := Pos('"><span>releases</span>', HTML);
if endPos > 0 then begin
	curPos := PrevPos('href="/movies', HTML, endPos);
	TmpStr := BASE_URL + Copy(HTML, curPos + 6, endPos - curPos - 6);
end;

if TmpStr <> '' then
	AddFieldValue(mfFeatures, '<link url="' + TmpStr + '">DVD Releases</link>');


//~mfTitle~ or ~Title~

curPos := Pos('<title>', HTML) + Length('<title>');

if Pos('- Cast, Reviews, Summary, and Awards - AllRovi</title>', HTML) > 0 then
	endPos := PosFrom('- Cast, Reviews, Summary, and Awards - AllRovi</title>', HTML, curPos)
else
	endPos := PosFrom('- Cast and Crew - AllRovi</title>', HTML, curPos);
TmpStr1 := Copy(HTML, curPos, endPos - curPos);

AddFieldValue(mfTitle, TmpStr1);  
AddCustomFieldValueByName('Title', TmpStr1);


//Save start position for Movie data
topPos := PosFrom('<div class="page-heading">', HTML, curPos)


//~mfYear~ or ~Year~

endPos := PosFrom('</span></h1>', HTML, curPos);
curPos := endPos - 5;
TmpStr2 := IntToStr(StrToInt(Copy(HTML, curPos, 4)));

if TmpStr2 = '0' then
	TmpStr2 := '';

AddFieldValue(mfYear, TmpStr2);
AddCustomFieldValueByName('Year', TmpStr2);

if TmpStr2 = '' then
	TmpStr2 := 'year unknown';
	
LogMessage('	Parsing:	' + TmpStr1 + '(' + TmpStr2 + ')');


//'Characteristics' saved as ~Characteristics~ ~Attibutes~ ~Moods~ (also as ~Mood links~)

TmpStr := '';
endPos := topPos;

TmpStr :=	HTMLValues(HTML,
			'<h3>characteristics</h3>', '<!--[if !IE 7]><!-->', //ItemEnd was '<div class="promo-frame">'
			'>- ', '</div>',
			', ', endPos);

//pull ~Attributes~ from 'Characteristics'
TmpStr1 := ''
if Pos('High Artistic Quality', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'High Artistic Quality';
TmpStr := StringReplace(TmpStr, 'High Artistic Quality, ', '', true, true, true);
if Pos('High Budget', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'High Budget';
TmpStr := StringReplace(TmpStr, 'High Budget, ', '', true, true, true);
if Pos('High Historical Importance', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'High Historical Importance';
TmpStr := StringReplace(TmpStr, 'High Historical Importance, ', '', true, true, true);
if Pos('High Production Values', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'High Production Values';
TmpStr := StringReplace(TmpStr, 'High Production Values, ', '', true, true, true);
if Pos('Low Artistic Quality', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'Low Artistic Quality';
TmpStr := StringReplace(TmpStr, 'Low Artistic Quality, ', '', true, true, true);
if Pos('Low Budget', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'Low Budget';
TmpStr := StringReplace(TmpStr, 'Low Budget, ', '', true, true, true);
if Pos('Low Production Values', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'Low Production Values';
TmpStr := StringReplace(TmpStr, 'Low Production Values, ', '', true, true, true);
if Pos('Cult Film', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'Cult Film';
TmpStr := StringReplace(TmpStr, 'Cult Film, ', '', true, true, true);
if Pos('Sleeper', TmpStr) > 0 then TmpStr1 := TmpStr1 + ', ' + 'Sleeper';
TmpStr := StringReplace(TmpStr, 'Sleeper, ', '', true, true, true);

//Pull ~Moods~ from 'Characteristics' and save ~Mood links~ if available
TmpStr2 := '';
TmpStr3 := '';
if Pos('A Good Cry', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'A Good Cry';
if Pos('A Good Cry', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://allmovie.com/explore/mood/a-good-cry-2028">A Good Cry</link>';
TmpStr := StringReplace(TmpStr, 'A Good Cry', '', true, true, true);
if Pos('A World of Its Own', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'A World of Its Own';
if Pos('A World of Its Own', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'A World of Its Own';
TmpStr := StringReplace(TmpStr, 'A World of Its Own', '', true, true, true);
if Pos('Abandon All Hope', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Abandon All Hope';
if Pos('Abandon All Hope', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/abandon-all-hope-2066">Abandon All Hope</link>';
TmpStr := StringReplace(TmpStr, 'Abandon All Hope', '', true, true, true);
if Pos('Adrenaline Rush', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Adrenaline Rush';
if Pos('Adrenaline Rush', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/adrenaline-rush-2026">Adrenaline Rush</link>';
TmpStr := StringReplace(TmpStr, 'Adrenaline Rush', '', true, true, true);
if Pos('Angsty', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Angsty';
if Pos('Angsty', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Angsty';
TmpStr := StringReplace(TmpStr, 'Angsty', '', true, true, true);
if Pos('Bad Taste', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Bad Taste';
if Pos('Bad Taste', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/bad-taste-2031">Bad Taste</link>';
TmpStr := StringReplace(TmpStr, 'Bad Taste', '', true, true, true);
if Pos('Blood and Gore', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Blood and Gore';
if Pos('Blood and Gore', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/blood-and-gore-260">Blood and Gore</link>';
TmpStr := StringReplace(TmpStr, 'Blood and Gore', '', true, true, true);
if Pos('Button Pushers', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Button Pushers';
if Pos('Button Pushers', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Button Pushers';
TmpStr := StringReplace(TmpStr, 'Button Pushers', '', true, true, true);
if Pos('Carnal Knowledge', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Carnal Knowledge';
if Pos('Carnal Knowledge', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/carnal-knowledge-262">Carnal Knowledge</link>';
TmpStr := StringReplace(TmpStr, 'Carnal Knowledge', '', true, true, true);
if Pos('Comedy on the Edge', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Comedy on the Edge';
if Pos('Comedy on the Edge', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/comedy-on-the-edge-2030">Comedy on the Edge</link>';
TmpStr := StringReplace(TmpStr, 'Comedy on the Edge', '', true, true, true);
if Pos('Estrogen Shot', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Estrogen Shot';
if Pos('Estrogen Shot', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Estrogen Shot';
TmpStr := StringReplace(TmpStr, 'Estrogen Shot', '', true, true, true);
if Pos('Eyepoppers', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Eyepoppers';
if Pos('Eyepoppers', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Eyepoppers';
TmpStr := StringReplace(TmpStr, 'Eyepoppers', '', true, true, true);
if Pos('Fantastic Reality', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Fantastic Reality';
if Pos('Fantastic Reality', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/fantastic-reality-2024">Fantastic Reality</link>';
TmpStr := StringReplace(TmpStr, 'Fantastic Reality', '', true, true, true);
if Pos('Flames of Passion', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Flames of Passion';
if Pos('Flames of Passion', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/flames-of-passion-262">Flames of Passion</link>';
TmpStr := StringReplace(TmpStr, 'Flames of Passion', '', true, true, true);
if Pos('Food for Thought', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Food for Thought';
if Pos('Food for Thought', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/food-for-thought-2032">Food for Thought</link>';
TmpStr := StringReplace(TmpStr, 'Food for Thought', '', true, true, true);
if Pos('For Love and Country', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'For Love of Country';
if Pos('For Love and Country', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/god-and-country-257">For Love and Country</link>';
TmpStr := StringReplace(TmpStr, 'For Love and Country', '', true, true, true);
if Pos('God and Country', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'God and Country';
if Pos('God and Country', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/god-and-country-257">God and Country</link>';
TmpStr := StringReplace(TmpStr, 'God and Country', '', true, true, true);
if Pos('Gutbusters', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Gutbusters';
if Pos('Gutbusters', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Gutbusters';
TmpStr := StringReplace(TmpStr, 'Gutbusters', '', true, true, true);
if Pos('Head Trips', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Head Trips';
if Pos('Head Trips', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://allmovie.com/explore/mood/head-trips-2035">Head Trips</link>';
TmpStr := StringReplace(TmpStr, 'Head Trips', '', true, true, true);
if Pos('High on Emotion', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'High on Emotion';
if Pos('High on Emotion', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/high-on-emotion-2028">High on Emotion</link>';
TmpStr := StringReplace(TmpStr, 'High on Emotion', '', true, true, true);
if Pos('In a Minor Key', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'In a Minor Key';
if Pos('In a Minor Key', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/in-a-minor-key-269">In a Minor Key</link>';
TmpStr := StringReplace(TmpStr, 'In a Minor Key', '', true, true, true);
if Pos('In the Mood for Love', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'In the Mood for Love';
if Pos('In the Mood for Love', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/in-the-mood-for-love-2027">In the Mood for Love</link>';
TmpStr := StringReplace(TmpStr, 'In the Mood for Love', '', true, true, true);
if Pos('Just for Fun', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Just for Fun';
if Pos('Just for Fun', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/just-for-fun-2029">Just for Fun</link>';
TmpStr := StringReplace(TmpStr, 'Just for Fun', '', true, true, true);
if Pos('Just for Laughs', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Just for Laughs';
if Pos('Just for Laughs', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/just-for-laughs-2029">Just for Laughs</link>';
TmpStr := StringReplace(TmpStr, 'Just for Laughs', '', true, true, true);
if Pos('Memory Lane', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Memory Lane';
if Pos('Memory Lane', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/memory-lane-2025">Memory Lane</link>';
TmpStr := StringReplace(TmpStr, 'Memory Lane', '', true, true, true);
if Pos('Mindbenders', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Mindbenders';
if Pos('Mindbenders', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/mindbenders-2035">Mindbenders</link>';
TmpStr := StringReplace(TmpStr, 'Mindbenders', '', true, true, true);
if Pos('Mood Enhancers', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Mood Enhancers';
if Pos('Mood Enhancers', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/mood-enhancers-2036">Mood Enhancers</link>';
TmpStr := StringReplace(TmpStr, 'Mood Enhancers', '', true, true, true);
if Pos('Nail-biters', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Nail-biters';
if Pos('Nail-biters', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/nail-biters-2037">Nail-biters</link>';
TmpStr := StringReplace(TmpStr, 'Nail-biters', '', true, true, true);
if Pos('Off the Beaten Path', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Off the Beaten Path';
if Pos('Off the Beaten Path', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Off the Beaten Path';
TmpStr := StringReplace(TmpStr, 'Off the Beaten Path', '', true, true, true);
if Pos('Only Human', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Only Human';
if Pos('Only Human', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/only-human-264">Only Human</link>';
TmpStr := StringReplace(TmpStr, 'Only Human', '', true, true, true);
if Pos('Other Dimensions', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Other Dimensions';
if Pos('Other Dimensions', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/other-dimensions-2038">Other Dimensions</link>';
TmpStr := StringReplace(TmpStr, 'Other Dimensions', '', true, true, true);
if Pos('Pick-Me-Ups', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Pick-Me-Ups';
if Pos('Pick-Me-Ups', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/pick-me-ups-2036">Pick-Me-Ups</link>';
TmpStr := StringReplace(TmpStr, 'Pick-Me-Ups', '', true, true, true);
if Pos('Slow Burn', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Slow Burn';
if Pos('Slow Burn', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Slow Burn';
TmpStr := StringReplace(TmpStr, 'Slow Burn', '', true, true, true);
if Pos('Spellbinders', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Spellbinders';
if Pos('Spellbinders', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/spellbinders-265">Spellbinders</link>';
TmpStr := StringReplace(TmpStr, 'Spellbinders', '', true, true, true);
if Pos('Strictly Speaking', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Strictly Speaking';
if Pos('Strictly Speaking', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/strictly-speaking-2034">Strictly Speaking</link>';
TmpStr := StringReplace(TmpStr, 'Strictly Speaking', '', true, true, true);
if Pos('Thrill Rides', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Thrill Rides';
if Pos('Thrill Rides', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/thrill-rides-2026">Thrill Rides</link>';
TmpStr := StringReplace(TmpStr, 'Thrill Rides', '', true, true, true);
if Pos('Tough Guys', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Tough Guys';
if Pos('Tough Guys', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/tough-guys-259">Tough Guys</link>';
TmpStr := StringReplace(TmpStr, 'Tough Guys', '', true, true, true);
if Pos('Trashy', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Trashy';
if Pos('Trashy', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/trashy-2031">Trashy</link>';
TmpStr := StringReplace(TmpStr, 'Trashy', '', true, true, true);
if Pos('Triumph of the Geeks', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Triumph of the Geeks';
if Pos('Triumph of the Geeks', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Triumph of the Geeks';
TmpStr := StringReplace(TmpStr, 'Triumph of the Geeks', '', true, true, true);
if Pos('Triumph of the Spirit', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Triumph of the Spirit';
if Pos('Triumph of the Spirit', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + '<link url="http://web.archive.org/web/http://www.allmovie.com/explore/mood/triumph-of-the-spirit-2033">Triumph of the Spirit</link>';
TmpStr := StringReplace(TmpStr, 'Triumph of the Spirit', '', true, true, true);
if Pos('Uncomfortable Viewing', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Uncomfortable Viewing';
if Pos('Uncomfortable Viewing', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Uncomfortable Viewing';
TmpStr := StringReplace(TmpStr, 'Uncomfortable Viewing', '', true, true, true);
if Pos('Unloveables', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Unloveables';
if Pos('Unloveables', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Unloveables';
TmpStr := StringReplace(TmpStr, 'Unloveables', '', true, true, true);
if Pos('Young and Old Alike', TmpStr) > 0 then TmpStr2 := TmpStr2 + ', ' + 'Young and Old Alike';
if Pos('Young and Old Alike', TmpStr) > 0 then TmpStr3 := TmpStr3 + ', ' + 'Young and Old Alike';
TmpStr := StringReplace(TmpStr, 'Young and Old Alike', '', true, true, true);

TmpStr := StringReplace(TmpStr, ' A ', ' a ', true, false, true);
TmpStr := StringReplace(TmpStr, ' An ', ' an ', true, false, true);
TmpStr := StringReplace(TmpStr, ' And ', ' and ', true, false, true);
TmpStr := StringReplace(TmpStr, ' & ', ' and ', true, false, true);
TmpStr := StringReplace(TmpStr, ' By ', ' by ', true, false, true);
TmpStr := StringReplace(TmpStr, ' For ', ' for ', true, false, true);
TmpStr := StringReplace(TmpStr, ' From ', ' from ', true, false, true);
TmpStr := StringReplace(TmpStr, ' In ', ' in ', true, false, true);
TmpStr := StringReplace(TmpStr, ' Into ', ' into ', true, false, true);
TmpStr := StringReplace(TmpStr, ' Of ', ' of ', true, false, true);
TmpStr := StringReplace(TmpStr, ' On ', ' on ', true, false, true);
TmpStr := StringReplace(TmpStr, ' Or ', ' or ', true, false, true);
TmpStr := StringReplace(TmpStr, ' The ', ' the ', true, false, true);
TmpStr := StringReplace(TmpStr, ' To ', ' to ', true, false, true);
TmpStr := StringReplace(TmpStr, ' With ', ' with ', true, false, true);
TmpStr := StringReplace(TmpStr, ' ,', '', true, true, true);
if Pos(', ', TmpStr) = 1 then Delete(TmpStr, 1, 2);
AddCustomFieldValueByName('Characteristics', TmpStr);

AddCustomFieldValueByName('Attributes', TmpStr1);

AddCustomFieldValueByName('Moods', TmpStr2);

Delete(TmpStr3, 1, 2);
AddCustomFieldValueByName('Mood links', TmpStr3);


//~Themes~ or optionally ~mfCategory~

TmpStr1 :='';
TmpStr2 :='';
if Pos('morebox', HTML) > 0 then
	TmpStr3 := 'morebox'
else
	TmpStr3 := '<div class="relatedResults">';

endPos := Pos('>Similarity</button>', HTML);
if endPos > 0 then
	TmpStr1 := HTMLValues(HTML,
				'>Similarity</button>', TmpStr3,
				'">', '</button>',
				', ', endPos);

if Pos('>Similarity</button>', HTML) = 0 then begin
	endPos := Pos('data-typeOp', HTML);
	TmpStr1 := HTMLValues(HTML,
				'data-typeOp', TmpStr3,
				'">', '</button>',
				', ', endPos);
end else

endPos := Pos('morebox', HTML);
if endPos > 0 then
	TmpStr2 := HTMLValues(HTML,
				'morebox', '<div class="relatedResults">',
				'''>', '</div>',
				', ', endPos);
Delete(TmpStr2, 1, Pos(', ', TmpStr2) + 1)

if TmpStr2 = '' then
	TmpStr := TmpStr1
else
	TmpStr := TmpStr1 + ', ' + TmpStr2;

TmpStr := StringReplace(TmpStr, 'Includes, ', '', true, true, true);
TmpStr := StringReplace(TmpStr, 'More, ', '', true, true, true);
TmpStr := StringReplace(TmpStr, ' A ', ' a ', true, false, true);
TmpStr := StringReplace(TmpStr, ' An ', ' an ', true, false, true);
TmpStr := StringReplace(TmpStr, ' And ', ' and ', true, false, true);
TmpStr := StringReplace(TmpStr, ' & ', ' and ', true, false, true);
TmpStr := StringReplace(TmpStr, ' By ', ' by ', true, false, true);
TmpStr := StringReplace(TmpStr, ' For ', ' for ', true, false, true);
TmpStr := StringReplace(TmpStr, ' From ', ' from ', true, false, true);
TmpStr := StringReplace(TmpStr, ' In ', ' in ', true, false, true);
TmpStr := StringReplace(TmpStr, ' Into ', ' into ', true, false, true);
TmpStr := StringReplace(TmpStr, ' Of ', ' of ', true, false, true);
TmpStr := StringReplace(TmpStr, ' On ', ' on ', true, false, true);
TmpStr := StringReplace(TmpStr, ' Or ', ' or ', true, false, true);
TmpStr := StringReplace(TmpStr, ' The ', ' the ', true, false, true);
TmpStr := StringReplace(TmpStr, ' To ', ' to ', true, false, true);
TmpStr := StringReplace(TmpStr, ' With ', ' with ', true, false, true);
TmpStr := StringReplace(TmpStr, ' ,', '', true, true, true);

if GET_THEMES then
	AddFieldValue(mfCategory, TmpStr);

AddCustomFieldValueByName('Themes', TmpStr)


//~Poster~

curPos := PosFrom('<img class="cover-art" src="', HTML, endPos);
if curPos > 0 then begin
	curPos := curPos + Length('<img class="cover-art" src="');
	endPos := PosFrom('.jpg', HTML, curPos);

TmpStr := Copy(HTML, curPos, endPos - curPos);
if TmpStr = '' then
	LogMessage('	Poster: 	Not available')
else									//else
	if GET_POSTER then
		ExtraLinks[smPoster] := Copy(HTML, curPos, endPos - curPos) + '.jpg'
	else
		ExtraLinks[smPoster] := '';
 end;


//~mfRating~ or ~Rovi rating~

endPos := topPos
TmpStr := Trim(HTMLValues(HTML,
				'<dt>rovi rating</dt>',  '</dd>',
				'<li class="star ', '"></li>',
				', ', endPos));

L := Length(TmpStr);
H := LastPos('half', TmpStr);

if H = 0 then
	R := (L + 2)/3
else
	R := (L + 2)/3 - 1;

if R > 0 then
	if GET_RATING then
		AddFieldValue(mfRating, IntToStr(R));
if R > 0 then
	AddCustomFieldValueByName('Rovi rating', IntToStr(R)); 
	
if R > 0 then
	LogMessage('	Rating:	' + IntToStr(R) + '/10')
else
	LogMessage('	Rating:	NR or error');


//~MPAA rating~

curPos := PosFrom('<dt>mpaa rating</dt>', HTML, endPos);
if curPos > 0 then begin
	curPos := PosFrom('<img src="/images/icon_', HTML, curPos) + 23;
	endPos := PosFrom('.png">', HTML, curPos);
	TmpStr  := Copy(HTML, curPos, endPos - curPos);
	TmpStr1 := StringReplace(TmpStr, '_', '', True, True, True);
	AddCustomFieldValueByName('MPAA rating', UpperCase(TmpStr1));
end else
curPos := endPos;

//handle 'not rated' - NR
curPos := PosFrom('<dt>mpaa rating</dt>', HTML, endPos);
if curPos > 0 then begin
	curPos := PosFrom('<dd>', HTML, curPos) + 4;
	endPos := PosFrom('</dd>', HTML, curPos);
	AddCustomFieldValueByName('MPAA rating', Copy(HTML, curPos, endPos - curPos));
end else
curPos := endPos;


//~Flags~

AddCustomFieldValueByName('Flags', HTMLValues(HTML,
								'<dt>flags</dt>', '</dd>',
								'<li>', '</li>',
								',  ', endPos));

//~mfGenre~ or ~Genres~

//endPos := topPos;
//TmpStr := HTMLValues(HTML, '<dt>genres</dt>', '</dd>', '">', '</a></li>', ',  ', endPos);

TmpStr := HTMLValues2(HTML,
			'<dt>genres</dt>', '</dd>',
			'<li>', '</li>',
			',  ', EndPos);

AddFieldValue(mfGenre, TmpStr)
AddCustomFieldValueByName('Genres', TmpStr)

//~Genre links~

TmpStr := '';
endPos := topPos;
curPos := PosFrom('<dt>genres</dt>', HTML, endPos);
if curPos > 0 then begin
	endPos := curPos;
	curPos := PosFrom('allrovi.com/movies/genre/', HTML, curPos);
	while (curPos > 0) AND (curPos < PosFrom('</ul>', HTML, endPos)) do begin
		curPos := curPos + Length('allrovi.com/movies/genre/');
		endPos := PosFrom('">', HTML, curPos);
		URL := 'http://www.allrovi.com/movies/genre/' + Copy(HTML, curPos, endPos - curPos);
		curPos := endPos + 2;
		endPos := PosFrom('</a>', HTML, curPos);
		Name := Copy(HTML, curPos, endPos - curPos);
		TmpStr := TmpStr + '<link url="' + URL + '">' + Name + '</link>, ';
		curPos := PosFrom('allrovi.com/movies/genre/', HTML, curPos);
	end;
	Delete(TmpStr, Length(TmpStr) - 1, 1);
	AddCustomFieldValueByName('Genre links', TmpStr);
end else
curPos := endPos;


//~Sub-Genres~

TmpStr := HTMLValues(HTML,
			'<dt>sub-genres</dt>', '</dd>',
			'<li>', '</li>',
			', ', endPos);
AddCustomFieldValueByName('Sub-Genres', TmpStr);


//~Sub-Genre links~

TmpStr := '';
endPos := topPos;
curPos := PosFrom('<dt>sub-genres</dt>', HTML, endPos);
if curPos > 0 then begin
	endPos := curPos;
	curPos := PosFrom('allrovi.com/movies/subgenre/', HTML, curPos);
	while (curPos > 0) AND (curPos < PosFrom('</ul>', HTML, endPos)) do begin
		curPos := curPos + Length('allrovi.com/movies/subgenre/');
		endPos := PosFrom('">', HTML, curPos);
		URL := 'http://www.allrovi.com/movies/subgenre/' + Copy(HTML, curPos, endPos - curPos);
		curPos := endPos + 2;
		endPos := PosFrom('</a>', HTML, curPos);
		Name := Copy(HTML, curPos, endPos - curPos);
		TmpStr := TmpStr + '<link url="' + URL + '">' + Name + '</link>, ';
		curPos := PosFrom('allrovi.com/movies/subgenre/', HTML, curPos);
	end;
	Delete(TmpStr, Length(TmpStr) - 1, 1);
	AddCustomFieldValueByName('Sub-Genre links', TmpStr);
end else
curPos := endPos;


//~Category.Rovi~

TmpStr := HTMLValues(HTML,
			'<dt>category</dt>', '</dd>',
			'<dd>', '</dd>',
			', ', endPos);
AddCustomFieldValueByName('Category.Rovi', TmpStr);


//~ctDirectors~

curPos := PosFrom('<dt>directed by</dt>', HTML, endPos);
if curPos > 0 then begin
	endPos := curPos;
	curPos := PosFrom('allrovi.com/name/', HTML, curPos);
	while (curPos > 0) AND (curPos < PosFrom('</ul>', HTML, endPos)) do begin
		curPos := curPos + Length('allrovi.com/name/');
		endPos := PosFrom('">', HTML, curPos);
		URL := 'http://www.allrovi.com/name/' + Copy(HTML, curPos, endPos - curPos);
		curPos := endPos + 2;
		endPos := PosFrom('</a>', HTML, curPos);
		Name := Copy(HTML, curPos, endPos - curPos);
		AddMoviePerson(Name, '', '', URL, ctDirectors);
		curPos := PosFrom('allrovi.com/name/', HTML, curPos);
	end;
end else
curPos := endPos;


//~mfCountry~ or ~Country~

TmpStr := HTMLValues(HTML,
			'<dt>countries</dt>', '</dd>',
			'<dd>', '</dd>',
			', ', endPos);
AddFieldValue(mfCountry, TmpStr);
AddCustomFieldValueByName('Country', TmpStr);


//~Released~

TmpStr := HTMLValues(HTML,
			'<dt>released</dt>', '<dt>run time</dt>',
			'<dd>', '</dd>',
			', ', endPos);
AddCustomFieldValueByName('Released', TmpStr);

//handle when named 'Release date' (used for multiple dates)
TmpStr := HTMLValues(HTML,
			'<dt>release date</dt>', '<dt>run time</dt>',
			'<li>', '</li>',
			'; ', endPos);
AddCustomFieldValueByName('Released', TmpStr);


//~Run time~ or ~mfDuration~

TmpStr :=	HTMLValues(HTML,
			'<dt>run time</dt>', 'd>',
			'<dd>', ' min.</dd>',
			', ', endPos);
if GET_DURATION then
 	AddFieldValue(mfDuration, TmpStr);
AddCustomFieldValueByName('Run time', TmpStr);


//~mfStudio~ or ~Produced by~

TmpStr := HTMLValues(HTML,
			'<dt>produced by</dt>', 'd>',
			'<dd>', '</d',
			', ', endPos);
AddFieldValue(mfStudio, TmpStr);
AddCustomFieldValueByName('Produced by', TmpStr);

//~Released by~

TmpStr := HTMLValues(HTML,
			'<dt>released by</dt>', '<dt>AMG ID</dt>',
			'<dd>', '</dd>',
			', ', endPos);
AddCustomFieldValueByName('Released by', TmpStr);

//~AMG ID~

TmpStr := HTMLValues(HTML,
			'<dt>AMG ID</dt>', '</dd>',
			'<pre>', '</pre>',
			', ', endPos);
AddCustomFieldValueByName('AMG ID', TmpStr);


//'Synopsis' saved to ~mfDescription~

curPos := PosFrom('<span>', HTML, curPos);
endPos := PosFrom('</span>', HTML, curPos);
TmpStr5 := TextBetween(HTML, '<span>', '</span>', True, curPos);

curPos := PosFrom('<span>by', HTML, curPos);
endPos := PosFrom('</span>', HTML, curPos);
TmpStr3 := TextBetween(HTML, '<span>by ', '</span>', True, curPos)

curPos := PosFrom('<strong>', HTML, curPos);
endPos := PosFrom('</strong>', HTML, curPos);
TmpStr4 := TextBetween(HTML, '<strong>', '</strong>', True, curPos);

curPos := PosFrom('<p>', HTML, curPos);
endPos := PosFrom('</p>', HTML, curPos);
TmpStr := Copy(HTML, curPos, endPos - curPos);
TmpStr1 := StringReplace(TmpStr, ' -- ', '—', True, True, False);
TmpStr2 := StringReplace(TmpStr1, ' --- ', '—', True, True, False);
TmpStr := StringReplace(TmpStr2, '--', '—', True, True, False);
TmpStr1 := StringReplace(TmpStr, #13#13#13#13, #13#10#13#10, True, True, False);
TmpStr2 := RemoveTagsEx(TmpStr1);

if (TmpStr4 = 'synopsis') AND (Pos('©', TmpStr2) = 0) then
	AddFieldValue(mfDescription, TmpStr2 + #13 + '—' + TmpStr3)
else
	if (TmpStr4 <> 'synopsis') OR (Pos('©', TmpStr2) = 1) then
		LogMessage('	Synopsis:	Not available');

end;


procedure ParseSearchResults(HTML : String);
var
	curPos, endPos : Integer;
	Title, Year, URL : String;
begin
	curPos := Pos('<div id="main" class="search-results movies">', HTML);
	if curPos < 1 then
		Exit;

LogMessage('Parsing search results...');

curPos := PosFrom('<a href="http://www.allrovi.com/movies/', HTML, curPos);
while curPos > 0 do begin
	endPos	:= PosFrom('" class="title">', HTML, curPos);
	URL		:= Copy(HTML, curPos + 31, endPos - curPos - 31);
	URL		:= BASE_URL + URL;
	
	curPos	:= PosFrom('" class="title">', HTML, curPos);
	endPos	:= PosFrom('</a>', HTML, curPos);
	Title	:= Copy(HTML, curPos + 16, endPos - curPos - 16);
	
	curPos	:= PosFrom('<dt>released:</dt>', HTML, curPos);
	curPos	:= PosFrom('<dd>', HTML, curPos);
	endPos	:= PosFrom('</dd>', HTML, curPos);
	Year		:= Trim(Copy(HTML, curPos + 4, endPos - curPos - 4));
	
	AddSearchResult(Title, '', Year, URL, '');
	curPos := PosFrom('" href="/movies/', HTML, curPos);
end;

//if there are more movies with the same or similar title...

curPos := Pos('<div class="results">', HTML);
if curPos < 1 then
	Exit;

curPos := PosFrom('<a href="http://www.allrovi.com/movies/', HTML, curPos);
while curPos > 0 do begin
	endPos	:= PosFrom('">', HTML, curPos);
	URL		:= Copy(HTML, curPos + 31, endPos - curPos - 31);
	URL		:= BASE_URL + URL;
	
	curPos	:= PosFrom('">', HTML, curPos);
	endPos	:= PosFrom('</a>', HTML, curPos);
	Title	:= Copy(HTML, curPos + 2, endPos - curPos - 2);
	
	curPos	:= PosFrom('<td class="year">', HTML, curPos);
	endPos	:= PosFrom('</td>', HTML, curPos);
	Year		:= Trim(Copy(HTML, curPos + 17, endPos - curPos - 17));

	AddSearchResult(Title, '', Year, URL, '');
	curPos := PosFrom('<a href="http://www.allrovi.com/movies/', HTML, curPos);
end;

end;


function NextMode(curMode : Integer) : Integer;
var
	I : Integer;
begin
Result := smFinished;
if curMode < Low(ExtraLinks) - 1 then
	curMode := Low(ExtraLinks) - 1;

for I := curMode + 1 to High(ExtraLinks) do
	if ExtraLinks[I] <> '' then begin
		Result := I;
		Break;
	end;
end;

function ParsePage(HTML : String; URL : AnsiString) : Cardinal;
begin
HTML := HTMLToText(HTML);
HTML := StringReplace (HTML, 'http://allrovi.com', 'http://www.allrovi.com', True, True, False);

if Pos('Search Results for', HTML) > 0 then begin
	ParseSearchResults(HTML);
	Result := prList;
	Exit;
end else

if (Mode = 0) AND (Pos('<h2>cast</h2>', HTML) > 0) then begin
	ParseMovie(URL, HTML);
	LogMessage('Getting main details from Cast & Crew page...');		
end else
	if (Mode = 0) AND (Pos('<h2>crew</h2>', HTML) > 0) then begin
		ParseMovie(URL, HTML);
		LogMessage('Getting main details from Cast & Crew page...');
	end else
		if (Mode = 0) AND (Pos('<strong>review</strong>', HTML) > 0) then begin
			ParseMovie(URL, HTML);
			LogMessage('Getting main details from Review page...');
		end else
			if (Mode = 0) AND (Pos('<h2>releases</h2>', HTML) > 0) then
				ParseMovie(URL, HTML)
			else
				if Pos('- Cast, Reviews, Summary, and Awards - AllRovi</title>', HTML) > 0 then
					ParseMovie(URL, HTML)
				else
					if Pos('- Review - AllRovi</title>', HTML) > 0 then
						ParseReview(HTML)
					else
						if Pos('- Cast and Crew - AllRovi</title>', HTML) > 0 then
							ParseCast(HTML)
						else
							if Pos('- Releases - AllRovi</title>', HTML) > 0 then
								ParseDVDReleases(HTML);

Mode := NextMode(Mode);
if Mode <> smFinished then
	Result := prDownload
else
	Result := prFinished;
end;

begin
Mode := smSearch;
for ELI := Low(ExtraLinks) to High(ExtraLinks) do
	ExtraLinks[ELI] := '';
end.