unit PlugServ;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
	Windows, ActiveX, Classes, ComObj, SysUtils, Feed,
		CM2GenInterface, CM2AutoUpdateInterface, CM2EditorSupportInterface;

type
  TFeeds = Record
    Name,
    Link: String;
    NumberOfItems,
    UpdateInterval: Integer;
  end;
	TCM2Feed = class(TComObject, ICM2GenPlug, ICM2AutoUpdate, ICM2EditorSupport10)
	private
		LastErrMsg: PChar;
		FirstRun: Boolean;
		Value, ItemVal, ItemNum, NumberOfFeeds: Integer;
    arFeeds: Array of TFeeds;
		arFeed: Array of TFeed;
		Procedure LoadReg;
		Procedure Parse(Param: String);
		Function FeedSensor(FeedNum: Integer) : String;
	protected
		Function Name(OUT Name: Pchar): HResult; stdcall;
		Function Version(OUT Version: word): HResult; stdcall;
		Function RequiredCoreVersion(OUT RCV: Word): HResult; stdcall;
		Function SetParentHandle(Handle: THandle): HResult; stdcall;
		Function GetLastErrorMsg(OUT Msg: PChar): HResult; stdcall;
		Function GetInfoCount(OUT InfoCount: Integer): HResult; stdcall;
		Function GetInfo(Index: Integer; OUT InfoName: PChar; OUT InfoVar: PChar): HResult; stdcall;
		Function GetSensorCount(OUT SensorCount: Integer): HResult; stdcall;
		Function GetSensorNameOnly(Index: Integer; OUT SensorName: PChar; OUT SensorStyle: Byte): HResult; stdcall;
		Function GetSensor(Index: Integer; Parameters: PChar; OUT SensorName: PChar; OUT SensorStyle: byte; OUT SensorString: PChar; OUT SensorValue: Double): HResult; stdcall;
		Function Init: HResult; stdcall;
		Function Terminating: HResult; stdcall;
		Function Setup: HResult; stdcall;
		Function GetDefaultCount(SensorIndex: Integer; OUT DefaultCount: Integer): HResult; stdcall;
		Function GetDefault(SensorIndex: Integer; Index: Integer; OUT Name: Pchar; OUT Value: PChar; OUT Description: PChar): HResult; stdcall;
		Function GetOptionalCount(SensorIndex: Integer; OUT OptionalCount: Integer): HResult; stdcall;
		Function GetOptional(SensorIndex: Integer; Index: Integer; OUT Name: Pchar; OUT Value: PChar; OUT Description: PChar): HResult; stdcall;
		Function UpdateFileURL(OUT URL: Pchar): HResult; stdcall;
		Function ShowSensor(Index: Integer; OUT ShowAt: Byte): HResult; stdcall;
		Function ObjIns(SensorIndex: Integer; ParameterName: PChar; OUT ValueType: Byte; OUT ValueRange: PChar): HResult; stdcall;
	End;

const
	Class_CM2Feed: TGUID = '{056D3A93-BD68-43FD-AA3A-8185C659FB93}';
	arChannel: Array [0..7] of String = ('FEED TYPE', 'FEED TITLE', 'FEED LINK', 'FEED DESCRIPTION',
    'FEED LANGUAGE', 'FEED PUBLISHED', 'FEED AUTHOR', 'ITEMS');
  arItem: Array[0..5] of String = ('TITLE', 'LINK', 'DESCRIPTION', 'CATEGORY', 'PUBLISHED', 'AUTHOR');

implementation

uses
	ComServ, Filter, Registry, FeedSetup;

{ TCM2WeatherDotCom }

function TCM2Feed.Name(out Name: PChar): HResult;
begin
	Name := 'Feed';
	Result := S_OK;
end;

function TCM2Feed.Version(out Version: Word): HResult;
begin
	Version := 0101;
	Result := S_OK;
end;

function TCM2Feed.UpdateFileURL(out URL: PChar): HResult;
begin
	URL := 'http://www.morbidmetal.org/cm2/Gen_Feed.upd';
	Result := S_OK;
end;

function TCM2Feed.RequiredCoreVersion(out RCV: Word): HResult;
begin
	RCV := 0500;
	Result := S_OK;
end;

function TCM2Feed.GetInfo(Index: Integer; out InfoName, InfoVar: PChar): HResult;
begin
	Result := S_OK;
	Case Index of
		0: Begin
			InfoName := 'Programmed By';
			InfoVar := 'Alch';
		End;
		1: Begin
			InfoName := 'Created';
			Infovar := 'November 8, 2006';
		End;
		2: Begin
			Infoname := 'Last Update';
			Infovar := 'November 29, 2006';
		End;
		3: Begin
			Infoname := 'Copyrights';
			Infovar := 'Alch - 2006';
		End;
		else begin
			Result := E_FAIL;
			LastErrMsg := 'Info Index Out of Bounds';
		End;
	End;
end;

function TCM2Feed.GetInfoCount(out InfoCount: Integer): HResult;
begin
	InfoCount := 4;
	Result := S_OK;
end;

function TCM2Feed.GetLastErrorMsg(OUT Msg: PChar): HResult;
begin
	If LastErrMsg = '' then
		LastErrMsg := 'No Errors';
	Msg := LastErrMsg;
	Result := S_OK;
end;

function TCM2Feed.GetSensorNameOnly(Index: Integer; OUT SensorName: PChar; OUT SensorStyle: Byte): HResult;
begin
	Result := S_OK;
  SensorName := PChar(arFeeds[index].Name);  
	SensorStyle := 1;
end;

function TCM2Feed.GetSensor(Index: Integer; Parameters: PChar; out SensorName: PChar;
	out Sensorstyle: Byte; out SensorString: PChar; out SensorValue: Double): HResult;
var
  i: integer;
begin
	Result := S_OK;
	if not FirstRun then
	begin
		FirstRun := True;
    for i := 0 to NumberOfFeeds -1 do
    begin
      SetLength(arFeed, i + 1);
      arFeed[i] := TFeed.Create(arFeeds[i].NumberOfItems, arFeeds[i].UpdateInterval, arFeeds[i].Link);
    end;
	end;

	Value := 0;
  ItemNum := 0;
  ItemVal := 0;
	if Parameters <> '' then
		Parse(Parameters);

  SensorName := PChar(arFeeds[Index].Name);
  SensorString := PChar(FeedSensor(Index));
	SensorStyle := 1;
	SensorValue := 0;
end;

function TCM2Feed.GetSensorCount(out SensorCount: Integer): HResult;
begin
	SensorCount := NumberOfFeeds;
	Result := S_OK;
end;

function TCM2Feed.FeedSensor(FeedNum: Integer): String;
var
  Num: Integer;
begin
  Num := arFeed[FeedNum].Count; 
  if ItemNum < 0 then
    ItemNum := 0
  else if ItemNum >= Num then
    ItemNum := Num -1;
    
	Case Value of
		0: Result := arFeed[FeedNum].FeedRec.Channel.FeedType;
		1: Result := arFeed[FeedNum].FeedRec.Channel.Title;
		2: Result := arFeed[FeedNum].FeedRec.Channel.Link;
		3: Result := arFeed[FeedNum].FeedRec.Channel.Description;
		4: Result := arFeed[FeedNum].FeedRec.Channel.Language;
		5: Result := arFeed[FeedNum].FeedRec.Channel.pubDate;
    6: Result := arFeed[FeedNum].FeedRec.Channel.Author;
    7: begin
      Case ItemVal of
        0: Result := arFeed[FeedNum].FeedRec.Item[ItemNum].Title;
        1: Result := arFeed[FeedNum].FeedRec.Item[ItemNum].Link;
        2: Result := arFeed[FeedNum].FeedRec.Item[ItemNum].Description;
        3: Result := arFeed[FeedNum].FeedRec.Item[ItemNum].Category;
        4: Result := arFeed[FeedNum].FeedRec.Item[ItemNum].pubDate;
        5: Result := arFeed[FeedNum].FeedRec.Item[ItemNum].Author;
      end;
    end;
	end;
end;

function TCM2Feed.Init: HResult;
begin
	Result := S_OK;
  NumberOfFeeds := 1;
  SetLength(arFeeds, 1);
  arFeeds[0].Name := 'BBC';
  arFeeds[0].Link:= 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml';
  arFeeds[0].NumberOfItems := 5;
  arFeeds[0].UpdateInterval := 30;
  LoadReg;
end;

procedure TCM2Feed.LoadReg;
var
  Reg: TRegistry;
  i, Num: Integer;
begin
  Reg := TRegistry.Create;
  With Reg do
  try
    if OpenKey(RegPath, false) then
    begin
      Num := ReadInteger('NumberOfFeeds');
      CloseKey;
      if (Num > 0) and OpenKey(RegPath + '\Feeds', false) then
      try
        NumberOfFeeds := Num;
        SetLength(arFeeds, Num);
        for i := 0 to Num -1 do
        begin
          arFeeds[i].Name := ReadString('Name' + IntToStr(i));
          arFeeds[i].Link := ReadString('Link' + IntToStr(i));
          arFeeds[i].NumberOfItems := ReadInteger('NumberOfItems' + IntToStr(i));
          arFeeds[i].UpdateInterval := ReadInteger('UpdateInterval' + IntToStr(i));
        end;
      finally
        CloseKey;
      end;
    end;
  finally
    Reg.Free;
  end;
end;

function TCM2Feed.SetParentHandle(Handle: THandle): HResult;
begin
	Result := S_OK;
end;

function TCM2Feed.Setup: HResult;
var
	FeedSetup: TfrmFeedSetup;
begin
	Result := S_OK;
	FeedSetup := TfrmFeedSetup.Create(nil);
	try
		try
			FeedSetup.Execute;
		except
			LastErrMsg := 'Setup Error';
			Result := E_FAIL;
		end;
	finally
		FreeAndNil(FeedSetup);
	end;
end;

function TCM2Feed.Terminating: HResult;
begin
	Result := S_OK;
  SetLength(arFeeds, 0);
  SetLength(arFeed, 0);
end;

function TCM2Feed.GetDefault(SensorIndex, Index: Integer; out Name, Value, Description: PChar): HResult;
begin
	Result := S_OK;
  Name := 'Value';
  Value := 'Feed Type';
  Description := 'Get Feed Data';
end;

function TCM2Feed.GetDefaultCount(SensorIndex: Integer; out DefaultCount: Integer): HResult;
begin
	DefaultCount := 1;
	Result := S_OK;
end;

function TCM2Feed.GetOptional(SensorIndex, Index: Integer; out Name, Value, Description: PChar): HResult;
begin
	Result := S_OK;
  Case Index of
    0: begin
      Name := 'ItemNumber';
      Value := '1';
      Description := 'Get Feed Item Number';
    end;
    1: begin
      Name := 'ItemValue';
      Value := 'Title';
      Description := 'Get Feed Item Data';
    end;
    else
			LastErrMsg := 'Optional Index Out of Bounds';
			Result := E_FAIL;
  end;
end;

function TCM2Feed.GetOptionalCount(SensorIndex: Integer; out OptionalCount: Integer): HResult;
begin
	OptionalCount := 2;
	Result := S_OK;
end;

procedure TCM2Feed.Parse(Param: String);
var
	i, j: Integer;
	S, N, V: String;
begin
	For i := 1 to CountFilt(Param, '|') do
	begin
		S := UpperCase(GetFilt(Param, i, '|')); 
		N := GetFilt(S, 1, '=');
		V := GetFilt(S, 2, '=');
		If N = 'VALUE' then
		begin
			For j := 0 to 7 do
				If V = arChannel[j] then
				begin
					Value := j;
					Continue;
				end;
		end;
    if N = 'ITEMVALUE' then
    begin
      For j := 0 to 5 do
        If V = arItem[j] then
        begin
          ItemVal := j;
          Continue;
        end;
    end;
    if N = 'ITEMNUMBER' then
    try
      ItemNum := StrToInt(V) -1;
    except
      ItemNum := 0;
    end;
	end;
end;

function TCM2Feed.ObjIns(SensorIndex: Integer; ParameterName: PChar; out ValueType: Byte; out ValueRange: PChar): HResult;
var
  N: String;
begin
	Result := S_OK;
	N := UpperCase(ParameterName);
	If N = 'VALUE' then
	begin                   
	  ValueType := vtFixed;
    ValueRange := 'Feed Type|Feed Title|Feed Link|Feed Description|Feed Language|Feed Published|Feed Author|Items';
    Exit;
	end;
	If N = 'ITEMVALUE' then
  begin
	  ValueType := vtFixed;
		ValueRange := 'Title|Link|Description|Category|Published|Author';
    Exit;
  end;
  if N = 'ITEMNUMBER' then
  begin
    ValueType := vtRange;
    ValueRange := '1|99';
  end;
end;

function TCM2Feed.ShowSensor(Index: Integer; out ShowAt: Byte): HResult;
begin
	Result := S_OK;
	ShowAt := saDesignTime;
end;

initialization
	TComObjectFactory.Create(ComServer, TCM2Feed, Class_CM2Feed,
		'CM2Gen_Feed', 'CoolMon 2 Feed Plugin', ciMultiInstance, tmApartment);
end.
