<?php

namespace Clevercherry\Backslash4\Models;

use Carbon\Carbon;
use Clevercherry\Backslash4\Backslash4;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class Block extends Model
{
    use scopeActive;
    private $datum = null;

    /**
     * Whether this block has subBlocks
     * @param  Model  $item      A Model - not used in this function but may be overriden in your app to do something special with it
     * @return Array             An array of string names for the block components
     */
    public function hasBlocks()
    {
        return !empty($this->getSubBlockNames($this));
    }

    /**
     * for blocks this is the name displayed in the top of the block on the block editor
     * so you can override it for certain block types to add data from the block
     * @return String
     */
    public function getNameTitle(): string
    {
        return ucwords(str_replace('.',' - ',Str::headline($this->type)));
    }

    /**
     * Adds disabled flag to block enabled/visible switch
     * @return bool      whether the switch should be disabled
     */
    public function blockSwitchIsReadOnly() : bool
    {
        return false;
    }

    public function getSubBlockFolder($item)
    {
        return Str::slug($this->type);
    }

    public function getSubBlockNames($item) : Array
    {
        $components=[];
        $paths = Config::get('view.paths');
        
        $folder = $this->getSubBlockFolder($item);

        if(!empty(config('backslash4.tenants-on',0)))
            $paths[] = Backslash4::getTenantPath('views');
        
        if(Config::get('backslash4.show-only-app-blocks')!=1)
            $paths[] = \Clevercherry\Backslash4\Backslash4ServiceProvider::packagePath('resources/views');
        
        foreach($paths as $path)
        {
            $rpath = $path.'/components/blocks-editable';
            if(!empty($folder))
                $rpath .= '/'.$folder;
            
            if(File::exists($rpath))
            {   $files = File::files($rpath);
                foreach($files as $file)
                {
                    if(Str::endsWith($file,'.blade.php'))
                    {   
                        $base = basename($file, ".blade.php");
                        
                        if($base!="no-block-found")
                        {
                            if(empty($folder))
                                $components[]= $base;
                            else
                                $components[]=  $folder.'.'.$base;
                        }
                    }
                }
            }
        }

        sort($components);
        return $components;
    }

    /**
     * Get the default list of /components/blocks editable
     * @param  Model $item      A Model
     * @param  Model $item      A Model if $item is a block then the parent item
     * @return Array            An array of string names for the block components
     * 
     * @deprecated use getBlockNamesExt()
     */
    public static function getBlockNames($item = null) : Array
    {
        return \App\Models\Block::getBlockNamesExt($item);
    }

    /**
     * Get the default list of /components/blocks editable
     * @param  Model $item      A Model
     * @param  Model $item      A Model if $item is a block then the parent item
     * @return Array            An array of string names for the block components
     */
    public static function getBlockNamesExt($item = null, $parentitem=null) : Array
    {

        if($item instanceof self)
        {
            //if this is a block asking for sub-blocks
            return $item->getSubBlockNames($parentitem);
        }

        $components=[];

        $paths = Config::get('view.paths');

        if(Config::get('backslash4.show-only-app-blocks')!=1)
            $paths[] = \Clevercherry\Backslash4\Backslash4ServiceProvider::packagePath('resources/views');

        if(!empty(config('backslash4.tenants-on',0)))
        {
            $p = Backslash4::getTenantPath('views');
            if(!empty($p))
            {   //dd(8642, $p );
                $paths[]=$p;
            }
        }
        
        foreach($paths as $path)
        {
            //echo("<!-- ccdev 136 : {$path} -->\n");
            File::ensureDirectoryExists($path.'/components/blocks-editable');
            $files = File::files($path.'/components/blocks-editable');
            foreach($files as $file)
            {
                if(Str::endsWith($file,'.blade.php'))
                {   
                    $base = basename($file, ".blade.php");
                    if($base!="no-block-found")
                        $components[]= $base;
                }
            }
        }

        sort($components);
        return $components;
    }

  

    public function searchCache() : bool
    {
        return false;
    }

    /**
     * return $this as a simplified json object for the data hidden field
     */
    public function stringify()
    {
        if(empty($this->data) || trim($this->data)=='{}')
            $datum=[];

        $datum = $this->getData();
        $datum['id'] = $this->id;
        $datum['type'] = $this->type;
        $datum['active'] = $this->active;
        if($this->model=='blocks')
            $datum['subblock']=true;
        //dd($datum);
        return json_encode($datum);
    }

    public function isChecked()
    {
        return $this->active ? 'checked="1"' : '';
    }
    /**
     * save the array of blocks[] passed in with the request object
     */
    public static function updateBlocks($modelClass, $id, $blocks)
    {
        $model = with(new ($modelClass))->getTable();
        //dd($model, $id, $blocks);
        
        $lastTopBlockId=null;
        $blockIds=[];
        $subBlockIds=[];

        foreach($blocks as $order => $json)
        {
            $data = json_decode($json, true);
            $blockID = @$data['id'];
            unset($data['id']);
            $type = @$data['type'];
            unset($data['type']);
            $active = @$data['active'];
            unset($data['active']);
            $subblock = !empty(@$data['subblock']);
            unset($data['subblock']);    

            $block=null;
            if(!empty($blockID))
                $block = self::where('id', $blockID)->first();
            
            if(empty($block))
            {
                $block = new Block;
                $block->type = $type;
                $block->model = $subblock ? 'blocks' : $model;
                $block->modelID = $subblock ? $lastTopBlockId : $id;
                $block->order = $order;
                $block->data = json_encode($data);
                $block->active = $active;
                
                //$fillable=['id', 'type', 'model', 'modelId', 'order', 'data', 'active', 
                //'created_at', 'updated_at'];
                //dd('ccdev 65', $newBlock);
                //dd($model, $newBlock);
                $block->save();
                
            } else
            {
                $block->order = $order;
                $block->data = json_encode($data);
                $block->active = $active;
                $block->updated_at = Carbon::now();

                $block->save();
            }

            if($subblock)
            {
                $subBlockIds[]=$block->id;
                
            } else
            {
                //not a sub block so may be the first block after we did a set of subblocks
                if(($lastTopBlockId != $block->id) && !empty($subBlockIds) )
                {
                    //lastTopBlockId has changed, so we finished a set of subblocks
                    //delete blocks that are no longer in the editor
                    self::where('model', 'blocks')->where('modelID', $lastTopBlockId)->whereNotIn('id', $subBlockIds)->delete();
                    $subBlockIds=[];
                }

                $blockIds[]=$block->id;
                $lastTopBlockId = $block->id;
            }
        }

        //delete blocks no longer in editor
        self::where('model', $model)->where('modelID', $id)->whereNotIn('id', $blockIds)->delete();        
    }

    /**
     * get the json data back as an associative object
     * buffer the data in a variable to save multiple json
     */
    public function getData($associative=true, $save=true)
    {
        // dont buffer/save data just return it
        if(!$save)
            return json_decode($this->data,$associative);
        
        //buffer the json decode
        if(!isset($this->datum) || ($this->datum == null))
        {   
            $this->datum = json_decode($this->data,$associative);
        }
        
        return $this->datum;
    }

    public function getItemLabel($index, $default='')
    {
        if(isset($this->getData()[$index]['label']))
            return $this->getData()[$index]['label'];
        
        //else
        return $default;
    }

    public function getItemData($index, $default='')
    {   
        if(isset($this->getData()[$index]['data']))
            return $this->getData()[$index]['data'];
        
        //else
        return $default;
    }

    public function putItemData($index, $value)
    {   
        $data = $this->getData();
        $data[$index]['data']=$value;
        
        $this->datum = $data;
        $this->data = json_encode($data);
    }

    function getMediaItemData($index)
    {
        $data=null;
        if(isset($this->getData()[$index]['data']))
            $data = $this->getData()[$index]['data'];
        
        if(empty($data) || !isset($data['id']))
        {
            // return null;
            $defaultmedia=MediaManager::defaultImage();
            $data = [ 'id' => $defaultmedia->id,
                      'alt' => basename($defaultmedia->bestPath()) ];
        }

        //else
        return $data;
    }

    /**
     * is the block deletable ?
     * You ,ay want to override this in the app dependent upon the blocks title field
     * @retrurn bool true
     */
    public function canDeleteBlock($item = null) : bool
    {
        return true;
    }
    /**
     * is the block moveable ?
     * You may want to override this in the app dependent upon the blocks title field
     * @retrurn bool true
     */
    public function canMoveBlock($item = null) : bool
    {
        return true;
    }

}